diff options
author | Norbert Preining <norbert@preining.info> | 2022-11-09 03:02:50 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2022-11-09 03:02:50 +0000 |
commit | 5de83ec843cdc88e6adc42b1fe3f0ec48c52b7f3 (patch) | |
tree | b49f7c180396c8ef389c8fd519370b6d03f4e100 /macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi | |
parent | 118cb5bbc5236bf86ca1088b9b3bae04c7b09beb (diff) |
CTAN sync 202211090302
Diffstat (limited to 'macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi')
36 files changed, 3124 insertions, 2503 deletions
diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/Parsetexi.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/Parsetexi.c index 0a123eeae6..565c42e7b4 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/Parsetexi.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/Parsetexi.c @@ -1,5 +1,5 @@ /* - * This file was generated automatically by ExtUtils::ParseXS version 3.34 from the + * This file was generated automatically by ExtUtils::ParseXS version 3.40 from the * contents of Parsetexi.xs. Do not edit this file, edit Parsetexi.xs instead. * * ANY CHANGES MADE HERE WILL BE LOST! @@ -7,6 +7,8 @@ */ #line 1 "parsetexi/Parsetexi.xs" +#include <config.h> + /* Avoid namespace conflicts. */ #define context perl_context @@ -24,7 +26,7 @@ #include "indices.h" #include "input.h" -#line 28 "parsetexi/Parsetexi.c" +#line 30 "parsetexi/Parsetexi.c" #ifndef PERL_UNUSED_VAR # define PERL_UNUSED_VAR(var) if (0) var = var #endif @@ -168,7 +170,7 @@ S_croak_xs_usage(const CV *const cv, const char *const params) # define newXS_deffile(a,b) Perl_newXS_deffile(aTHX_ a,b) #endif -#line 172 "parsetexi/Parsetexi.c" +#line 174 "parsetexi/Parsetexi.c" XS_EUPXS(XS_Texinfo__Parser_init); /* prototype to pass -Wmissing-prototypes */ XS_EUPXS(XS_Texinfo__Parser_init) @@ -191,23 +193,6 @@ XS_EUPXS(XS_Texinfo__Parser_init) } -XS_EUPXS(XS_Texinfo__Parser_dump_errors); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_Texinfo__Parser_dump_errors) -{ - dVAR; dXSARGS; - if (items != 0) - croak_xs_usage(cv, ""); - { - char * RETVAL; - dXSTARG; - - RETVAL = dump_errors(); - sv_setpv(TARG, RETVAL); XSprePUSH; PUSHTARG; - } - XSRETURN(1); -} - - XS_EUPXS(XS_Texinfo__Parser_wipe_errors); /* prototype to pass -Wmissing-prototypes */ XS_EUPXS(XS_Texinfo__Parser_wipe_errors) { @@ -241,17 +226,37 @@ XS_EUPXS(XS_Texinfo__Parser_parse_file) } +XS_EUPXS(XS_Texinfo__Parser_parse_piece); /* prototype to pass -Wmissing-prototypes */ +XS_EUPXS(XS_Texinfo__Parser_parse_piece) +{ + dVAR; dXSARGS; + if (items != 2) + croak_xs_usage(cv, "string, line_nr"); + { + char * string = (char *)SvPV_nolen(ST(0)) +; + int line_nr = (int)SvIV(ST(1)) +; + + parse_piece(string, line_nr); + } + XSRETURN_EMPTY; +} + + XS_EUPXS(XS_Texinfo__Parser_parse_string); /* prototype to pass -Wmissing-prototypes */ XS_EUPXS(XS_Texinfo__Parser_parse_string) { dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "string"); + if (items != 2) + croak_xs_usage(cv, "string, line_nr"); { char * string = (char *)SvPV_nolen(ST(0)) ; + int line_nr = (int)SvIV(ST(1)) +; - parse_string(string); + parse_string(string, line_nr); } XSRETURN_EMPTY; } @@ -261,13 +266,15 @@ XS_EUPXS(XS_Texinfo__Parser_parse_text); /* prototype to pass -Wmissing-prototyp XS_EUPXS(XS_Texinfo__Parser_parse_text) { dVAR; dXSARGS; - if (items != 1) - croak_xs_usage(cv, "string"); + if (items != 2) + croak_xs_usage(cv, "string, line_nr"); { char * string = (char *)SvPV_nolen(ST(0)) ; + int line_nr = (int)SvIV(ST(1)) +; - parse_text(string); + parse_text(string, line_nr); } XSRETURN_EMPTY; } @@ -588,8 +595,8 @@ XS_EUPXS(XS_Texinfo__Parser_conf_set_IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME) } -XS_EUPXS(XS_Texinfo__Parser_set_novalidate); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_Texinfo__Parser_set_novalidate) +XS_EUPXS(XS_Texinfo__Parser_set_DOC_ENCODING_FOR_INPUT_FILE_NAME); /* prototype to pass -Wmissing-prototypes */ +XS_EUPXS(XS_Texinfo__Parser_set_DOC_ENCODING_FOR_INPUT_FILE_NAME) { dVAR; dXSARGS; if (items != 1) @@ -598,14 +605,14 @@ XS_EUPXS(XS_Texinfo__Parser_set_novalidate) int i = (int)SvIV(ST(0)) ; - set_novalidate(i); + set_DOC_ENCODING_FOR_INPUT_FILE_NAME(i); } XSRETURN_EMPTY; } -XS_EUPXS(XS_Texinfo__Parser_set_documentlanguage); /* prototype to pass -Wmissing-prototypes */ -XS_EUPXS(XS_Texinfo__Parser_set_documentlanguage) +XS_EUPXS(XS_Texinfo__Parser_conf_set_input_file_name_encoding); /* prototype to pass -Wmissing-prototypes */ +XS_EUPXS(XS_Texinfo__Parser_conf_set_input_file_name_encoding) { dVAR; dXSARGS; if (items != 1) @@ -614,7 +621,39 @@ XS_EUPXS(XS_Texinfo__Parser_set_documentlanguage) char * value = (char *)SvPV_nolen(ST(0)) ; - set_documentlanguage(value); + conf_set_input_file_name_encoding(value); + } + XSRETURN_EMPTY; +} + + +XS_EUPXS(XS_Texinfo__Parser_conf_set_locale_encoding); /* prototype to pass -Wmissing-prototypes */ +XS_EUPXS(XS_Texinfo__Parser_conf_set_locale_encoding) +{ + dVAR; dXSARGS; + if (items != 1) + croak_xs_usage(cv, "value"); + { + char * value = (char *)SvPV_nolen(ST(0)) +; + + conf_set_locale_encoding(value); + } + XSRETURN_EMPTY; +} + + +XS_EUPXS(XS_Texinfo__Parser_conf_set_documentlanguage_override); /* prototype to pass -Wmissing-prototypes */ +XS_EUPXS(XS_Texinfo__Parser_conf_set_documentlanguage_override) +{ + dVAR; dXSARGS; + if (items != 1) + croak_xs_usage(cv, "value"); + { + char * value = (char *)SvPV_nolen(ST(0)) +; + + conf_set_documentlanguage_override(value); } XSRETURN_EMPTY; } @@ -635,6 +674,41 @@ XS_EUPXS(XS_Texinfo__Parser_set_debug) XSRETURN_EMPTY; } + +XS_EUPXS(XS_Texinfo__Parser_set_accept_internalvalue); /* prototype to pass -Wmissing-prototypes */ +XS_EUPXS(XS_Texinfo__Parser_set_accept_internalvalue) +{ + dVAR; dXSARGS; + if (items != 0) + croak_xs_usage(cv, ""); + { + + set_accept_internalvalue(); + } + XSRETURN_EMPTY; +} + + +XS_EUPXS(XS_Texinfo__Parser_get_errors); /* prototype to pass -Wmissing-prototypes */ +XS_EUPXS(XS_Texinfo__Parser_get_errors) +{ + dVAR; dXSARGS; + if (items != 0) + croak_xs_usage(cv, ""); + { + AV * RETVAL; + + RETVAL = get_errors(); + { + SV * RETVALSV; + RETVALSV = newRV((SV*)RETVAL); + RETVALSV = sv_2mortal(RETVALSV); + ST(0) = RETVALSV; + } + } + XSRETURN(1); +} + #ifdef __cplusplus extern "C" #endif @@ -664,11 +738,11 @@ XS_EXTERNAL(boot_Texinfo__Parser) #endif (void)newXSproto_portable("Texinfo::Parser::init", XS_Texinfo__Parser_init, file, "$$"); - (void)newXSproto_portable("Texinfo::Parser::dump_errors", XS_Texinfo__Parser_dump_errors, file, ""); (void)newXSproto_portable("Texinfo::Parser::wipe_errors", XS_Texinfo__Parser_wipe_errors, file, ""); (void)newXSproto_portable("Texinfo::Parser::parse_file", XS_Texinfo__Parser_parse_file, file, "$"); - (void)newXSproto_portable("Texinfo::Parser::parse_string", XS_Texinfo__Parser_parse_string, file, "$"); - (void)newXSproto_portable("Texinfo::Parser::parse_text", XS_Texinfo__Parser_parse_text, file, "$"); + (void)newXSproto_portable("Texinfo::Parser::parse_piece", XS_Texinfo__Parser_parse_piece, file, "$$"); + (void)newXSproto_portable("Texinfo::Parser::parse_string", XS_Texinfo__Parser_parse_string, file, "$$"); + (void)newXSproto_portable("Texinfo::Parser::parse_text", XS_Texinfo__Parser_parse_text, file, "$$"); (void)newXSproto_portable("Texinfo::Parser::store_value", XS_Texinfo__Parser_store_value, file, "$$"); (void)newXSproto_portable("Texinfo::Parser::wipe_values", XS_Texinfo__Parser_wipe_values, file, ""); (void)newXSproto_portable("Texinfo::Parser::reset_context_stack", XS_Texinfo__Parser_reset_context_stack, file, ""); @@ -687,9 +761,13 @@ XS_EXTERNAL(boot_Texinfo__Parser) (void)newXSproto_portable("Texinfo::Parser::conf_set_show_menu", XS_Texinfo__Parser_conf_set_show_menu, file, "$"); (void)newXSproto_portable("Texinfo::Parser::conf_set_CPP_LINE_DIRECTIVES", XS_Texinfo__Parser_conf_set_CPP_LINE_DIRECTIVES, file, "$"); (void)newXSproto_portable("Texinfo::Parser::conf_set_IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME", XS_Texinfo__Parser_conf_set_IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME, file, "$"); - (void)newXSproto_portable("Texinfo::Parser::set_novalidate", XS_Texinfo__Parser_set_novalidate, file, "$"); - (void)newXSproto_portable("Texinfo::Parser::set_documentlanguage", XS_Texinfo__Parser_set_documentlanguage, file, "$"); + (void)newXSproto_portable("Texinfo::Parser::set_DOC_ENCODING_FOR_INPUT_FILE_NAME", XS_Texinfo__Parser_set_DOC_ENCODING_FOR_INPUT_FILE_NAME, file, "$"); + (void)newXSproto_portable("Texinfo::Parser::conf_set_input_file_name_encoding", XS_Texinfo__Parser_conf_set_input_file_name_encoding, file, "$"); + (void)newXSproto_portable("Texinfo::Parser::conf_set_locale_encoding", XS_Texinfo__Parser_conf_set_locale_encoding, file, "$"); + (void)newXSproto_portable("Texinfo::Parser::conf_set_documentlanguage_override", XS_Texinfo__Parser_conf_set_documentlanguage_override, file, "$"); (void)newXSproto_portable("Texinfo::Parser::set_debug", XS_Texinfo__Parser_set_debug, file, "$"); + (void)newXSproto_portable("Texinfo::Parser::set_accept_internalvalue", XS_Texinfo__Parser_set_accept_internalvalue, file, ""); + (void)newXSproto_portable("Texinfo::Parser::get_errors", XS_Texinfo__Parser_get_errors, file, ""); #if PERL_VERSION_LE(5, 21, 5) # if PERL_VERSION_GE(5, 9, 0) if (PL_unitcheckav) diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/Parsetexi.pm b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/Parsetexi.pm index ee88072f24..25f3672ae1 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/Parsetexi.pm +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/Parsetexi.pm @@ -1,4 +1,4 @@ -# Copyright 2014-2020 Free Software Foundation, Inc. +# Copyright 2014-2022 Free Software Foundation, Inc. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -13,7 +13,35 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +# Since there are different parser implementation, XS and NonXS, it is +# better to have the Texinfo::Parser packages define only the parser +# API functions. Constants, functions useful in both parsers, and other +# functions useful in other codes are better defined in other Texinfo +# modules. + # File to be loaded in conjunction with Parsetexi.xs module +# +# FIXME two customization keys are duplicated from the main parser in +# gdt(), which are set and used by the NonXS parser, 'kbdinputstyle' +# and 'clickstyle'. The XS parser does not set nor use those keys, so +# their values are not passed to gdt(). +# As long as there is no other code that sets those keys to another value than +# their default value, and that there are no translated strings containing the +# @-commands whose output is modified by those customization keys, however, +# the difference between the parsers won't have any visible effect. + +# In general, the Parser works with character strings decoded from the +# command line, from input files or from the parsed document and returns +# character strings. There are exceptions for the following files and +# directory names that are binary strings: +# * the input file name passed through parse_texi_file is a binary string +# * the 'file_name' values in 'source_info' from convert_errors and in +# the tree elements 'source_info' are returned as binary strings +# +# The following parser information is directly determined from the +# input file name as binary strings +# ->{'info'}->{'input_file_name'} +# ->{'info'}->{'input_directory'} package Texinfo::Parser; @@ -21,26 +49,32 @@ use 5.00405; use strict; use warnings; -require Exporter; +# To check if there is no erroneous autovivification +#no autovivification qw(fetch delete exists store strict); + +use Storable qw(dclone); # standard in 5.007003 +use Encode qw(decode); use Texinfo::Common; -use Texinfo::Encoding; -use Texinfo::Convert::NodeNameNormalization; use Texinfo::Report; +use Texinfo::Convert::NodeNameNormalization; +use Texinfo::Translations; + +require Exporter; -our @ISA = qw(Exporter DynaLoader Texinfo::Report); +our @ISA = qw(Exporter); our %EXPORT_TAGS = ( 'all' => [ qw( parser - parse_texi_text - parse_texi_line parse_texi_file + parse_texi_line + parse_texi_piece + parse_texi_text ) ] ); our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); -our @EXPORT = qw( - -); +my %parser_default_configuration = + (%Texinfo::Common::default_parser_customization_values); sub get_conf($$) { @@ -49,17 +83,11 @@ sub get_conf($$) return $self->{$var}; } -my %parser_default_configuration = - (%Texinfo::Common::default_parser_state_configuration, - %Texinfo::Common::default_parser_customization_values); - -use Storable qw(dclone); # standard in 5.007003 - sub simple_parser { goto &parser; } -# Stub for Texinfo::Parser::parser +# Initialize the parser sub parser (;$$) { my $conf = shift; @@ -69,33 +97,27 @@ sub parser (;$$) reset_parser (); if (defined($conf)) { foreach my $key (keys (%$conf)) { - # Copy conf to parser object. Not used in parser module itself - # but some settings may be used elsewhere, especially in - # Structuring.pm. - if ($key ne 'values' and ref($conf->{$key})) { + # Copy conf to parser object. + # we keep registrar instead of copying on purpose, to reuse the object + if ($key ne 'values' and $key ne 'registrar' and ref($conf->{$key})) { $parser->{$key} = dclone($conf->{$key}); } else { $parser->{$key} = $conf->{$key}; } - if ($key eq 'include_directories') { - foreach my $d (@{$conf->{'include_directories'}}) { + if ($key eq 'INCLUDE_DIRECTORIES') { + foreach my $d (@{$conf->{'INCLUDE_DIRECTORIES'}}) { add_include_directory ($d); } } elsif ($key eq 'values') { - # This is used by Texinfo::Report::gdt for substituted values - for my $v (keys %{$conf->{'values'}}) { - if (!ref($conf->{'values'}->{$v})) { - store_value ($v, $conf->{'values'}->{$v}); - } elsif (ref($conf->{'values'}->{$v}) eq 'HASH') { - store_value ($v, "<<HASH VALUE>>"); - } elsif (ref($conf->{'values'}->{$v}) eq 'ARRAY') { - store_value ($v, "<<ARRAY VALUE>>"); - } else { - store_value ($v, "<<UNKNOWN VALUE>>"); - } - } - } elsif ($key eq 'expanded_formats') { + for my $v (keys %{$conf->{'values'}}) { + if (ref($conf->{'values'}->{$v}) eq '') { + store_value ($v, $conf->{'values'}->{$v}); + } else { + warn "bug: non-scalar \@value\n"; + } + } + } elsif ($key eq 'EXPANDED_FORMATS') { clear_expanded_formats (); for my $f (@{$conf->{$key}}) { @@ -103,11 +125,7 @@ sub parser (;$$) } } elsif ($key eq 'documentlanguage') { if (defined ($conf->{$key})) { - set_documentlanguage ($conf->{$key}); - } - } elsif ($key eq 'info') { - if (defined($conf->{$key}->{'novalidate'})) { - set_novalidate($conf->{$key}->{'novalidate'}); + conf_set_documentlanguage_override ($conf->{$key}); } } elsif ($key eq 'FORMAT_MENU') { if ($conf->{$key} eq 'menu') { @@ -120,11 +138,17 @@ sub parser (;$$) } elsif ($key eq 'CPP_LINE_DIRECTIVES') { conf_set_CPP_LINE_DIRECTIVES($conf->{$key}); } elsif ($key eq 'DEBUG') { - set_debug($conf->{$key}) if $conf->{'key'}; - } elsif ($key eq 'in_gdt' - or $key eq 'ENABLE_ENCODING' - or defined($Texinfo::Common::default_structure_customization_values{$key})) { - # no action needed + set_debug($conf->{$key}) if $conf->{$key}; + } elsif ($key eq 'DOC_ENCODING_FOR_INPUT_FILE_NAME') { + set_DOC_ENCODING_FOR_INPUT_FILE_NAME ($conf->{$key}); + } elsif ($key eq 'INPUT_FILE_NAME_ENCODING' and defined($conf->{$key})) { + conf_set_input_file_name_encoding ($conf->{$key}); + } elsif ($key eq 'LOCALE_ENCODING' and defined($conf->{$key})) { + conf_set_locale_encoding ($conf->{$key}); + } elsif ($key eq 'accept_internalvalue') { + set_accept_internalvalue(); + } elsif ($key eq 'registrar' or $key eq 'COMMAND_LINE_ENCODING') { + # no action needed, only used in perl code } else { warn "ignoring parser configuration value \"$key\"\n"; } @@ -133,12 +157,10 @@ sub parser (;$$) bless $parser; - $parser->Texinfo::Report::new; - return $parser; } -# Record any @menu elements under $root in the 'menus' array of $node. +# Record any @menu elements under $root in the extra 'menus' array of $node. sub _find_menus_of_node { my $node = shift; my $root = shift; @@ -147,7 +169,7 @@ sub _find_menus_of_node { my $contents = $root->{'contents'}; foreach my $child (@{$contents}) { if ($child->{'cmdname'} and $child->{'cmdname'} eq 'menu') { - push @{$node->{'menus'}}, $child; + push @{$node->{'extra'}->{'menus'}}, $child; } } } @@ -155,13 +177,10 @@ sub _find_menus_of_node { # Set 'menus' array for each node. This accounts for malformed input where # the number of sectioning commands between @node and @menu is not exactly 1. -sub _complete_node_menus { +sub _associate_node_menus { my $self = shift; my $root = shift; - if (!defined $self->{'nodes'}) { - $self->{'nodes'} = []; - } my $node; foreach my $child (@{$root->{'contents'}}) { if ($child->{'cmdname'} and $child->{'cmdname'} eq 'node') { @@ -171,106 +190,88 @@ sub _complete_node_menus { } } -sub get_parser_info { +sub _get_error_registrar($) +{ my $self = shift; + if (not $self->{'registrar'}) { + $self->{'registrar'} = Texinfo::Report::new(); + } + my $registrar = $self->{'registrar'}; + my $configuration_information = $self; + return $registrar, $configuration_information; +} - my ($TARGETS, $INTL_XREFS, $FLOATS, - $INDEX_NAMES, $ERRORS, $GLOBAL_INFO, $GLOBAL_INFO2); +# done after all the parsings. Part may not make much sense for parse_texi_line, +# we nevertheless do it in any case to do the same as in ParserNonXS +sub _set_errors_node_lists_labels_indices($) +{ + my $self = shift; - $TARGETS = build_label_list (); - $INTL_XREFS = build_internal_xref_list (); - $FLOATS = build_float_list (); + my $TARGETS = build_label_list (); + $self->{'targets'} = $TARGETS; + + _get_errors ($self); + # Setup labels info and nodes list based on 'targets' + Texinfo::Convert::NodeNameNormalization::set_nodes_list_labels($self, + $self->{'registrar'}, $self); - $INDEX_NAMES = build_index_data (); + my $INDEX_NAMES = build_index_data (); $self->{'index_names'} = $INDEX_NAMES; + Texinfo::Translations::complete_indices ($self); +} + +sub get_parser_info { + my $self = shift; + + my ($INTL_XREFS, $FLOATS, $ERRORS, $GLOBAL_INFO, $GLOBAL_INFO2); + $INTL_XREFS = build_internal_xref_list (); + $FLOATS = build_float_list (); $GLOBAL_INFO = build_global_info (); $GLOBAL_INFO2 = build_global_info2 (); - $self->{'targets'} = $TARGETS; - $self->{'labels'} = {}; $self->{'internal_references'} = $INTL_XREFS; $self->{'floats'} = $FLOATS; $self->{'info'} = $GLOBAL_INFO; - $self->{'extra'} = $GLOBAL_INFO2; - - # Propagate these settings from 'info' hash to 'values' hash. - # The 'values' hash is not otherwise used. Maybe we should use - # the 'info' hash for this instead in the pure Perl code. - for my $txi_flag ('txiindexatsignignore', 'txiindexbackslashignore', - 'txiindexhyphenignore', 'txiindexlessthanignore') { - if ($self->{'info'}->{$txi_flag}) { - $self->{'values'}->{$txi_flag} = 1; - } - } + $self->{'commands_info'} = $GLOBAL_INFO2; - _get_errors ($self); - Texinfo::Common::complete_indices ($self); + _set_errors_node_lists_labels_indices($self); } use File::Basename; # for fileparse -# Handle 'IGNORE_BEFORE_SETFILENAME' conf value. -# Put everything before @setfilename in a special type. This allows -# ignoring everything before @setfilename. -sub _maybe_ignore_before_setfilename { - my ($self, $text_root) = @_; - - if ($self->{'IGNORE_BEFORE_SETFILENAME'} and $text_root - and $self->{'extra'}->{'setfilename'} - and $self->{'extra'}->{'setfilename'}->{'parent'} eq $text_root) { - my $before_setfilename = {'type' => 'preamble_before_setfilename', - 'parent' => $text_root, - 'contents' => []}; - while (@{$text_root->{'contents'}} - and (!$text_root->{'contents'}->[0]->{'cmdname'} - or $text_root->{'contents'}->[0]->{'cmdname'} ne 'setfilename')) { - my $content = shift @{$text_root->{'contents'}}; - $content->{'parent'} = $before_setfilename; - push @{$before_setfilename->{'contents'}}, $content; - } - if (!@{$text_root->{'contents'}}) { - # not found - #splice @{$text_root->{'contents'}}, 0, 0, @$before_setfilename; - $text_root->{'contents'} = $before_setfilename->{'contents'}; - } else { - unshift (@{$text_root->{'contents'}}, $before_setfilename) - if (@{$before_setfilename->{'contents'}}); - } - } -} - # Replacement for Texinfo::Parser::parse_texi_file sub parse_texi_file ($$) { my $self = shift; - my $file_name = shift; + my $input_file_path = shift; my $tree_stream; - my $status = parse_file ($file_name); + my $status = parse_file ($input_file_path); if ($status) { - # TODO: internationalise this message? - $self->document_error(sprintf("could not open %s: %s", $file_name, $!)); + my ($registrar, $configuration_information) = _get_error_registrar($self); + my $input_file_name = $input_file_path; + my $encoding = $self->get_conf('COMMAND_LINE_ENCODING'); + if (defined($encoding)) { + $input_file_name = decode($encoding, $input_file_path); + } + $registrar->document_error($configuration_information, + sprintf(__("could not open %s: %s"), $input_file_name, $!)); return undef; } my $TREE = build_texinfo_tree (); get_parser_info ($self); - _complete_node_menus ($self, $TREE); - - my $text_root; - if ($TREE->{'type'} eq 'text_root') { - $text_root = $TREE; - } elsif ($TREE->{'contents'} and $TREE->{'contents'}->[0] - and $TREE->{'contents'}->[0]->{'type'} eq 'text_root') { - $text_root = $TREE->{'contents'}->[0]; - } - _maybe_ignore_before_setfilename($self, $text_root); + _associate_node_menus ($self, $TREE); + + my $before_node_section = $TREE->{'contents'}->[0]; + + Texinfo::Common::rearrange_tree_beginning($self, $before_node_section); ############################################################ - my ($basename, $directories, $suffix) = fileparse($file_name); + my ($basename, $directories, $suffix) = fileparse($input_file_path); $self->{'info'}->{'input_file_name'} = $basename; $self->{'info'}->{'input_directory'} = $directories; @@ -278,77 +279,113 @@ sub parse_texi_file ($$) } # Copy the errors into the error list in Texinfo::Report. -# TODO: Could we just access the error list directly instead of going -# through Texinfo::Report line_error? sub _get_errors($) { my $self = shift; - my $ERRORS; - my $tree_stream = dump_errors(); - eval $tree_stream; + my ($registrar, $configuration_information) = _get_error_registrar($self); + + my $ERRORS = get_errors (); + for my $error (@{$ERRORS}) { if ($error->{'type'} eq 'error') { - $self->line_error ($error->{'message'}, $error->{'line_nr'}); + $registrar->line_error ($configuration_information, + $error->{'message'}, $error->{'source_info'}); } else { - $self->line_warn ($error->{'message'}, $error->{'line_nr'}); + $registrar->line_warn ($configuration_information, + $error->{'message'}, $error->{'source_info'}); } } } + +# Replacement for Texinfo::Parser::parse_texi_piece +# +# Used in tests under tp/t. +sub parse_texi_piece($$;$$$$) +{ + my $self = shift; + my $text = shift; + my $lines_nr = shift; + my $file = shift; + my $macro = shift; + my $fixed_line_number = shift; + + return undef if (!defined($text)); + + $lines_nr = 1 if (not defined($lines_nr)); + + $self = parser() if (!defined($self)); + + # make sure that internal byte buffer is in UTF-8 before we pass + # it in to the XS code. + utf8::upgrade($text); + + parse_piece($text, $lines_nr); + my $tree = build_texinfo_tree (); + + get_parser_info($self); + _associate_node_menus ($self, $tree); + + return $tree; +} + # Replacement for Texinfo::Parser::parse_texi_text # # Used in tests under tp/t. sub parse_texi_text($$;$$$$) { - my $self = shift; - my $text = shift; - my $lines_nr = shift; - my $file = shift; - my $macro = shift; - my $fixed_line_number = shift; - - return undef if (!defined($text)); - - $self = parser() if (!defined($self)); - - # make sure that internal byte buffer is in UTF-8 before we pass - # it in to the XS code. - utf8::upgrade($text); - - parse_text($text); - my $tree = build_texinfo_tree (); - my $INDEX_NAMES = build_index_data (); - $self->{'index_names'} = $INDEX_NAMES; - - for my $index (keys %$INDEX_NAMES) { - if ($INDEX_NAMES->{$index}->{'merged_in'}) { - $self->{'merged_indices'}-> {$index} - = $INDEX_NAMES->{$index}->{'merged_in'}; - } - } + my $self = shift; + my $text = shift; + my $lines_nr = shift; + my $file = shift; + my $macro = shift; + my $fixed_line_number = shift; + + return undef if (!defined($text)); + + $lines_nr = 1 if (not defined($lines_nr)); + + $self = parser() if (!defined($self)); + + # make sure that internal byte buffer is in UTF-8 before we pass + # it in to the XS code. + utf8::upgrade($text); - get_parser_info($self); - _complete_node_menus ($self, $tree); - return $tree; + parse_text($text, $lines_nr); + my $tree = build_texinfo_tree (); + + get_parser_info($self); + + _associate_node_menus ($self, $tree); + + my $before_node_section = $tree->{'contents'}->[0]; + + Texinfo::Common::rearrange_tree_beginning($self, $before_node_section); + return $tree; } # Replacement for Texinfo::Parser::parse_texi_line sub parse_texi_line($$;$$$$) { - my $self = shift; - my $text = shift; - my $lines_nr = shift; - my $file = shift; - my $macro = shift; - my $fixed_line_number = shift; - - return undef if (!defined($text)); - - $self = parser() if (!defined($self)); - utf8::upgrade($text); - parse_string($text); - my $tree = build_texinfo_tree (); - return $tree; + my $self = shift; + my $text = shift; + my $lines_nr = shift; + my $file = shift; + my $macro = shift; + my $fixed_line_number = shift; + + return undef if (!defined($text)); + + $lines_nr = 1 if (not defined($lines_nr)); + + $self = parser() if (!defined($self)); + utf8::upgrade($text); + parse_string($text, $lines_nr); + my $tree = build_texinfo_tree (); + + _set_errors_node_lists_labels_indices($self); + + return $tree; } # Public interfaces of Texinfo::Parser @@ -356,11 +393,6 @@ sub indices_information($) { my $self = shift; - my $INDEX_NAMES; - if (!$self->{'index_names'}) { - $INDEX_NAMES = build_index_data (); - $self->{'index_names'} = $INDEX_NAMES; - } return $self->{'index_names'}; } @@ -379,20 +411,28 @@ sub internal_references_information($) sub global_commands_information($) { my $self = shift; - return $self->{'extra'}; + return $self->{'commands_info'}; } -sub global_informations($) +sub global_information($) { my $self = shift; return $self->{'info'}; } -# Setup labels and nodes info and return labels sub labels_information($) { - goto &Texinfo::Common::labels_information; + my $self = shift; + return $self->{'labels'}, $self->{'targets'}, $self->{'nodes'}; +} + +sub registered_errors($) +{ + my $self = shift; + return $self->{'registrar'}; } 1; __END__ + +The POD documentation of Texinfo::Parser is in Texinfo::ParserNonXS. diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/Parsetexi.xs b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/Parsetexi.xs index 66cd76e145..d5972061fa 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/Parsetexi.xs +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/Parsetexi.xs @@ -1,3 +1,5 @@ +#include <config.h> + /* Avoid namespace conflicts. */ #define context perl_context @@ -24,9 +26,6 @@ init (texinfo_uninstalled, srcdir) int texinfo_uninstalled char *srcdir -char * -dump_errors () - void wipe_errors () @@ -35,12 +34,19 @@ parse_file(filename) char * filename void -parse_string(string) +parse_piece(string, line_nr) + char * string + int line_nr + +void +parse_string(string, line_nr) char * string + int line_nr void -parse_text(string) +parse_text(string, line_nr) char * string + int line_nr void store_value (name, value) @@ -101,11 +107,25 @@ void conf_set_IGNORE_SPACE_AFTER_BRACED_COMMAND_NAME (int i) void -set_novalidate (int i) +set_DOC_ENCODING_FOR_INPUT_FILE_NAME (int i) + +void +conf_set_input_file_name_encoding (value) + char *value void -set_documentlanguage (value) +conf_set_locale_encoding (value) + char *value + +void +conf_set_documentlanguage_override (value) char *value void set_debug (int i) + +void +set_accept_internalvalue() + +AV * +get_errors () diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/api.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/api.c index f85ceff097..8066dcad0c 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/api.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/api.c @@ -1,4 +1,4 @@ -/* Copyright 2010-2021 Free Software Foundation, Inc. +/* Copyright 2010-2022 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,6 +21,11 @@ #define PERL_NO_GET_CONTEXT #include "EXTERN.h" #include "perl.h" +/* Avoid warnings about Perl headers redefining symbols that gnulib + redefined already. */ +#if defined _WIN32 && !defined __CYGWIN__ + #undef free +#endif #include "XSUB.h" #undef context @@ -44,11 +49,9 @@ ELEMENT *Root; #define LOCALEDIR DATADIR "/locale" -/* Use the uninstalled locales dir. - NB the texinfo.mo files are not actually created here, only the - texinfo_document.mo files, which aren't used by parsetexi. - Hence, error messages will be translated only when the program is - installed. */ +/* Use the uninstalled locales dir. Currently unused. + The texinfo.mo files are not actually created here, only the + texinfo_document.mo files, which aren't used by parsetexi. */ static void find_locales_dir (char *builddir) { @@ -83,11 +86,9 @@ init (int texinfo_uninstalled, char *builddir) { setlocale (LC_ALL, ""); - /* Use installed or uninstalled translation files for gettext. */ - if (texinfo_uninstalled) - find_locales_dir (builddir); - else - bindtextdomain (PACKAGE, LOCALEDIR); + /* Note: this uses the installed translations even when running an + uninstalled program. */ + bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); @@ -141,42 +142,102 @@ reset_parser_except_conf (void) void reset_parser (void) { + /* NOTE: Do not call 'malloc' or 'free' in this function or in any function + called in this file. Since this file (api.c) includes the Perl headers, + we get the Perl redefinitions, which we do not want, as we don't use + them throughout the rest of the program. */ + debug ("!!!!!!!!!!!!!!!! RESETTING THE PARSER !!!!!!!!!!!!!!!!!!!!!"); reset_parser_except_conf (); wipe_values (); clear_expanded_formats (); + clear_include_directories (); reset_conf (); + + global_documentlanguage_fixed = 0; + set_documentlanguage (0); + + doc_encoding_for_input_file_name = 1; + set_input_file_name_encoding (0); + set_locale_encoding (0); + + global_accept_internalvalue = 0; } -/* Set ROOT to root of tree obtained by parsing FILENAME. */ +/* Determine directory path based on file name. + Set ROOT to root of tree obtained by parsing FILENAME. + Used for parse_texi_file. */ int parse_file (char *filename) { + /* debug_output = 0; - Root = parse_texi_file (filename); + */ + char *p, *q; + char c; + + int status; + + status = input_push_file (filename); + if (status) + return status; + + /* Strip off a leading directory path, by looking for the last + '/' in filename. */ + p = 0; + q = strchr (filename, '/'); + while (q) + { + p = q; + q = strchr (q + 1, '/'); + } + + if (p) + { + c = *p; + *p = '\0'; + add_include_directory (filename); + *p = c; + } + + Root = parse_texi_document (); if (Root) return 0; return 1; } +/* Used for parse_texi_text. STRING should be a UTF-8 buffer. */ +void +parse_text (char *string, int line_nr) +{ + reset_parser_except_conf (); + input_push_text_with_line_nos (strdup (string), line_nr); + Root = parse_texi_document (); +} + /* Set ROOT to root of tree obtained by parsing the Texinfo code in STRING. STRING should be a UTF-8 buffer. Used for parse_texi_line. */ void -parse_string (char *string) +parse_string (char *string, int line_nr) { + ELEMENT *root_elt = new_element (ET_root_line); + reset_parser_except_conf (); - input_push_text (strdup (string), 0); - Root = parse_texi (new_element (ET_root_line)); + input_push_text_with_line_nos (strdup (string), line_nr); + Root = parse_texi (root_elt, root_elt); } -/* Used for parse_texi_text. STRING should be a UTF-8 buffer. */ +/* Used for parse_texi_piece. STRING should be a UTF-8 buffer. */ void -parse_text (char *string) +parse_piece (char *string, int line_nr) { + ELEMENT *before_node_section = setup_document_root_and_before_node_section (); + ELEMENT *document_root = before_node_section->parent; + reset_parser_except_conf (); - input_push_text_with_line_nos (strdup (string), 1); - Root = parse_texi (new_element (ET_text_root)); + input_push_text_with_line_nos (strdup (string), line_nr); + Root = parse_texi (document_root, before_node_section); } @@ -245,6 +306,19 @@ build_node_spec (NODE_SPEC_EXTRA *value) return newRV_inc ((SV *)hv); } +/* Used to create a "Perl-internal" string that represents a sequence + of Unicode codepoints with no specific encoding. */ +static SV * +newSVpv_utf8 (char *str, STRLEN len) +{ + SV *sv; + dTHX; + + sv = newSVpv (str, len); + SvUTF8_on (sv); + return sv; +} + /* Set E->hv and 'hv' on E's descendants. e->parent->hv is assumed to already exist. */ static void @@ -280,46 +354,11 @@ element_to_perl_hash (ELEMENT *e) sv = newSVpv (command_name(e->cmd), 0); hv_store (e->hv, "cmdname", strlen ("cmdname"), sv, 0); - /* TODO: Same optimizations as for 'type'. */ + /* Note we could optimize the call to newSVpv here and + elsewhere by passing an appropriate second argument. */ } - /* A lot of special cases for when an empty contents array should be - created. Largely by trial and error to match the Perl code. Some of - them don't make sense, like @arrow{}, @image, or for accent commands. */ - if (e->contents.number > 0 - || e->type == ET_text_root - || e->type == ET_root_line - || e->type == ET_bracketed - || e->type == ET_bracketed_def_content - || e->type == ET_line_arg - || e->cmd == CM_image - || e->cmd == CM_item && e->parent && e->parent->type == ET_row - || e->cmd == CM_headitem && e->parent && e->parent->type == ET_row - || e->cmd == CM_tab && e->parent && e->parent->type == ET_row - || e->cmd == CM_anchor - || e->cmd == CM_macro - || e->cmd == CM_multitable - || e->type == ET_menu_entry_name - || e->type == ET_menu_entry_description - || e->type == ET_brace_command_arg - || e->type == ET_brace_command_context - || e->type == ET_block_line_arg - || e->type == ET_before_item - || e->type == ET_inter_item - || e->cmd == CM_TeX - || e->type == ET_elided - || e->type == ET_elided_block - || e->type == ET_preformatted - || e->type == ET_paragraph - || (command_flags(e) & CF_root) - || (command_data(e->cmd).flags & CF_brace - && (command_data(e->cmd).data >= 0 - || command_data(e->cmd).data == BRACE_style - || command_data(e->cmd).data == BRACE_context - || command_data(e->cmd).data == BRACE_other - || command_data(e->cmd).data == BRACE_accent - )) - || e->cmd == CM_node) + if (e->contents.number > 0) { AV *av; int i; @@ -353,22 +392,8 @@ element_to_perl_hash (ELEMENT *e) if (e->text.space > 0) { - sv = newSVpv (e->text.text, e->text.end); - if (e->cmd != CM_value) - hv_store (e->hv, "text", strlen ("text"), sv, 0); - else - hv_store (e->hv, "type", strlen ("type"), sv, 0); - - SvUTF8_on (sv); - /* The strings here have to be in UTF-8 to start with. - This leads to an unnecessary round trip with "@documentencoding - ISO-8859-1" for Info and plain text output, when we first convert the - characters in the input file to UTF-8, and convert them back again for - the output. - - The alternative is to leave the UTF-8 flag off, and hope that Perl - interprets 8-bit encodings like ISO-8859-1 correctly. See - "How does Perl store UTF-8 strings?" in "man perlguts". */ + sv = newSVpv_utf8 (e->text.text, e->text.end); + hv_store (e->hv, "text", strlen ("text"), sv, 0); } if (e->extra_number > 0) @@ -434,7 +459,7 @@ element_to_perl_hash (ELEMENT *e) case extra_string: { /* A simple string. */ char *value = (char *) f; - STORE(newSVpv (value, 0)); + STORE(newSVpv_utf8 (value, 0)); break; } case extra_integer: @@ -456,15 +481,14 @@ element_to_perl_hash (ELEMENT *e) { if (f->contents.list[j]->text.end > 0) { - av_push (av, - newSVpv (f->contents.list[j]->text.text, - f->contents.list[j]->text.end)); + SV *sv = newSVpv_utf8 (f->contents.list[j]->text.text, + f->contents.list[j]->text.end); + av_push (av, sv); } else { /* Empty strings permitted. */ - av_push (av, - newSVpv ("", 0)); + av_push (av, newSVpv ("", 0)); } } break; @@ -528,8 +552,10 @@ element_to_perl_hash (ELEMENT *e) hv_store (type, "content", strlen ("content"), build_perl_array (&eft->content->contents), 0); if (eft->normalized) - hv_store (type, "normalized", strlen ("normalized"), - newSVpv (eft->normalized, 0), 0); + { + SV *sv = newSVpv_utf8 (eft->normalized, 0); + hv_store (type, "normalized", strlen ("normalized"), sv, 0); + } STORE(newRV_inc ((SV *)type)); break; } @@ -545,30 +571,29 @@ element_to_perl_hash (ELEMENT *e) newRV_inc((SV *)extra), 0); } - if (e->line_nr.line_nr - && !(command_flags(e) & CF_INFOENCLOSE)) + if (e->source_info.line_nr) { #define STORE(key, sv) hv_store (hv, key, strlen (key), sv, 0) - LINE_NR *line_nr = &e->line_nr; + SOURCE_INFO *source_info = &e->source_info; HV *hv = newHV (); - hv_store (e->hv, "line_nr", strlen ("line_nr"), + hv_store (e->hv, "source_info", strlen ("source_info"), newRV_inc((SV *)hv), 0); - if (line_nr->file_name) + if (source_info->file_name) { - STORE("file_name", newSVpv (line_nr->file_name, 0)); + STORE("file_name", newSVpv (source_info->file_name, 0)); } else STORE("file_name", newSVpv ("", 0)); - if (line_nr->line_nr) + if (source_info->line_nr) { - STORE("line_nr", newSViv (line_nr->line_nr)); + STORE("line_nr", newSViv (source_info->line_nr)); } - if (line_nr->macro) + if (source_info->macro) { - STORE("macro", newSVpv (line_nr->macro, 0)); + STORE("macro", newSVpv_utf8 (source_info->macro, 0)); } else STORE("macro", newSVpv ("", 0)); @@ -579,6 +604,13 @@ element_to_perl_hash (ELEMENT *e) HV * build_texinfo_tree (void) { + if (! Root) + /* use an empty element with contents if there is nothing. + This should only happen if the input file was not opened + or no parse_* function was called after initialization + and should not happen with the current calling code. + */ + Root = new_element (ET_NONE); element_to_perl_hash (Root); return Root->hv; } @@ -689,7 +721,7 @@ build_single_index_data (INDEX *i) hv = (HV *) i->hv; } - STORE("name", newSVpv (i->name, 0)); + STORE("name", newSVpv_utf8 (i->name, 0)); STORE("in_code", i->in_code ? newSViv(1) : newSViv(0)); if (i->merged_in) @@ -711,7 +743,7 @@ build_single_index_data (INDEX *i) hv_store (ultimate->contained_hv, i->name, strlen (i->name), newSViv (1), 0); - STORE("merged_in", newSVpv (ultimate->name, 0)); + STORE("merged_in", newSVpv_utf8 (ultimate->name, 0)); if (i->contained_hv) { @@ -753,17 +785,17 @@ build_single_index_data (INDEX *i) e = &i->index_entries[j]; entry = newHV (); - STORE2("index_name", newSVpv (i->name, 0)); + STORE2("index_name", newSVpv_utf8 (i->name, 0)); STORE2("index_at_command", newSVpv (command_name(e->index_at_command), 0)); STORE2("index_type_command", newSVpv (command_name(e->index_type_command), 0)); - STORE2("command", + STORE2("entry_element", newRV_inc ((SV *)e->command->hv)); - STORE2("number", newSViv (entry_number)); + STORE2("entry_number", newSViv (entry_number)); if (e->region) { - STORE2("region", newRV_inc ((SV *)e->region->hv)); + STORE2("entry_region", newRV_inc ((SV *)e->region->hv)); } if (e->content) { @@ -787,14 +819,14 @@ build_single_index_data (INDEX *i) if (contents_array) { /* Copy the reference to the array. */ - STORE2("content", newRV_inc ((SV *)(AV *)SvRV(*contents_array))); + STORE2("entry_content", newRV_inc ((SV *)(AV *)SvRV(*contents_array))); STORE2("content_normalized", newRV_inc ((SV *)(AV *)SvRV(*contents_array))); } else { - STORE2("content", newRV_inc ((SV *)newAV ())); + STORE2("entry_content", newRV_inc ((SV *)newAV ())); STORE2("content_normalized", newRV_inc ((SV *)newAV ())); } } @@ -802,18 +834,29 @@ build_single_index_data (INDEX *i) ; /* will be set in Texinfo::Common::complete_indices */ if (e->node) - STORE2("node", newRV_inc ((SV *)e->node->hv)); + STORE2("entry_node", newRV_inc ((SV *)e->node->hv)); if (e->sortas) - STORE2("sortas", newSVpv (e->sortas, 0)); + STORE2("sortas", newSVpv_utf8 (e->sortas, 0)); - /* Skip these as these entries do not refer to the place in the document - where the index commands occurred. */ - if (!lookup_extra (e->command, "seeentry") - && !lookup_extra (e->command, "seealso")) - { - av_push (entries, newRV_inc ((SV *)entry)); - entry_number++; - } + /* Create ignored_chars hash. */ + { +#define STORE3(key) hv_store (hv, key, strlen (key), newSViv(1), 0) + HV *hv = newHV (); + if (e->ignored_chars.backslash) + STORE3("\\"); + if (e->ignored_chars.hyphen) + STORE3("-"); + if (e->ignored_chars.lessthan) + STORE3("<"); + if (e->ignored_chars.atsign) + STORE3("@"); +#undef STORE3 + + STORE2("index_ignore_chars", newRV_inc ((SV *)hv)); + } + + av_push (entries, newRV_inc ((SV *)entry)); + entry_number++; /* We set this now because the index data structures don't exist at the time that the main tree is built. */ @@ -861,7 +904,7 @@ build_index_data (void) /* Return object to be used as $self->{'info'} in the Perl code, retrievable - with the 'global_informations' function. */ + with the 'global_information' function. */ HV * build_global_info (void) { @@ -892,22 +935,6 @@ build_global_info (void) } } - if (global_info.novalidate) - { - hv_store (hv, "novalidate", strlen ("novalidate"), - newSVpv ("1", 0), 0); - } - - char *txi_flags[] = { "txiindexatsignignore", "txiindexbackslashignore", - "txiindexhyphenignore", "txiindexlessthanignore", 0}; - char **p; - - for (p = txi_flags; (*p); p++) - { - if (fetch_value (*p)) - hv_store (hv, *p, strlen (*p), newSVpv ("1", 0), 0); - } - return hv; } @@ -958,6 +985,7 @@ build_global_info2 (void) BUILD_GLOBAL_UNIQ(oddfootingmarks); BUILD_GLOBAL_UNIQ(shorttitlepage); BUILD_GLOBAL_UNIQ(title); + BUILD_GLOBAL_UNIQ(novalidate); #undef BUILD_GLOBAL_UNIQ /* NOTE: Same list in handle_commands.c:register_global_command. */ @@ -1001,7 +1029,7 @@ build_global_info2 (void) BUILD_GLOBAL_ARRAY(detailmenu); BUILD_GLOBAL_ARRAY(part); - /* from Common.pm %document_settable_at_commands */ + /* from Common.pm %document_settable_multiple_at_commands */ BUILD_GLOBAL_ARRAY(allowcodebreaks); BUILD_GLOBAL_ARRAY(clickstyle); BUILD_GLOBAL_ARRAY(codequotebacktick); @@ -1029,3 +1057,114 @@ set_debug (int value) debug_output = value; } +void +conf_set_documentlanguage_override (char *value) +{ + set_documentlanguage_override (value); +} + + +void +set_DOC_ENCODING_FOR_INPUT_FILE_NAME (int i) +{ + doc_encoding_for_input_file_name = i; +} + +void +conf_set_input_file_name_encoding (char *value) +{ + set_input_file_name_encoding (value); +} + +void +conf_set_locale_encoding (char *value) +{ + set_locale_encoding (value); +} + + +static SV * +build_source_info_hash (SOURCE_INFO source_info) +{ + HV *hv; + + dTHX; + + hv = newHV (); + + if (source_info.file_name) + { + hv_store (hv, "file_name", strlen ("file_name"), + newSVpv (source_info.file_name, 0), 0); + } + else + { + hv_store (hv, "file_name", strlen ("file_name"), + newSVpv ("", 0), 0); + } + if (source_info.line_nr) + { + hv_store (hv, "line_nr", strlen ("line_nr"), + newSViv (source_info.line_nr), 0); + } + if (source_info.macro) + { + hv_store (hv, "macro", strlen ("macro"), + newSVpv_utf8 (source_info.macro, 0), 0); + } + else + { + hv_store (hv, "macro", strlen ("macro"), + newSVpv_utf8 ("", 0), 0); + } + + return newRV_inc ((SV *) hv); +} + +static SV * +convert_error (int i) +{ + ERROR_MESSAGE e; + HV *hv; + SV *msg; + + dTHX; + + e = error_list[i]; + hv = newHV (); + + msg = newSVpv_utf8 (e.message, 0); + + hv_store (hv, "message", strlen ("message"), msg, 0); + hv_store (hv, "type", strlen ("type"), + e.type == error ? newSVpv("error", strlen("error")) + : newSVpv("warning", strlen("warning")), + 0); + + hv_store (hv, "source_info", strlen ("source_info"), + build_source_info_hash(e.source_info), 0); + + return newRV_inc ((SV *) hv); + +} + +/* Errors */ +AV * +get_errors (void) +{ + AV *av; + int i; + + dTHX; + + av = newAV (); + + for (i = 0; i < error_number; i++) + { + SV *sv = convert_error (i); + av_push (av, sv); + } + + return av; + +} diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/api.h b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/api.h index 7843680255..626c3b4c7d 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/api.h +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/api.h @@ -5,15 +5,21 @@ extern ELEMENT *Root; int init (int texinfo_uninstalled, char *srcdir_in); -void parse_text (char *); -void parse_string(char *); int parse_file (char *filename); +void parse_piece (char *, int line_nr); +void parse_string (char *, int line_nr); +void parse_text (char *, int line_nr); void reset_parser (void); void reset_parser_except_conf (void); void set_debug (int); void wipe_values (void); void reset_context_stack (void); +void set_DOC_ENCODING_FOR_INPUT_FILE_NAME (int i); +void conf_set_input_file_name_encoding (char *value); +void conf_set_locale_encoding (char *value); +void conf_set_documentlanguage_override (char *value); + HV *build_texinfo_tree (void); AV *build_label_list (void); AV *build_internal_xref_list (void); @@ -21,6 +27,6 @@ HV *build_float_list (void); HV *build_index_data (void); HV *build_global_info (void); HV *build_global_info2 (void); - +AV *get_errors (void); #endif diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/close.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/close.c index 2568be2052..08b2113a08 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/close.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/close.c @@ -23,7 +23,7 @@ /* Possibly print an error message, and return CURRENT->parent. */ static ELEMENT * close_brace_command (ELEMENT *current, - enum command_id closed_command, + enum command_id closed_block_command, enum command_id interrupting_command) { @@ -37,10 +37,10 @@ close_brace_command (ELEMENT *current, if (0) { yes: - if (closed_command) + if (closed_block_command) command_error (current, "@end %s seen before @%s closing brace", - command_name(closed_command), + command_name(closed_block_command), command_name(current->cmd)); else if (interrupting_command) command_error (current, @@ -67,14 +67,14 @@ yes: paragraphs. */ ELEMENT * close_all_style_commands (ELEMENT *current, - enum command_id closed_command, + enum command_id closed_block_command, enum command_id interrupting_command) { while (current->parent && (command_flags(current->parent) & CF_brace) && !(command_data(current->parent->cmd).data == BRACE_context)) current = close_brace_command (current->parent, - closed_command, interrupting_command); + closed_block_command, interrupting_command); return current; } @@ -163,7 +163,7 @@ close_command_cleanup (ELEMENT *current) int have_leading_spaces = 0; ELEMENT *before_item = 0; if (current->contents.number >= 2 - && current->contents.list[0]->type == ET_empty_line_after_command + && current->contents.list[0]->type == ET_ignorable_spaces_after_command && current->contents.list[1]->type == ET_before_item) { have_leading_spaces = 1; @@ -178,10 +178,8 @@ close_command_cleanup (ELEMENT *current) if (before_item) { /* Reparent @end from a ET_before_item to the block command */ - KEY_PAIR *k = lookup_extra (current, "end_command"); - ELEMENT *e = k ? k->value : 0; - if (k && last_contents_child (before_item) - && last_contents_child (before_item) == e) + ELEMENT *e = last_contents_child (before_item); + if (e && e->cmd == CM_end) { add_to_element_contents (current, pop_element_from_contents (before_item)); @@ -221,7 +219,7 @@ close_command_cleanup (ELEMENT *current) && (e->cmd != CM_c && e->cmd != CM_comment && e->cmd != CM_end) || e->type != ET_NONE - && e->type != ET_empty_line_after_command) + && e->type != ET_ignorable_spaces_after_command) { empty_format = 0; break; @@ -237,9 +235,34 @@ close_command_cleanup (ELEMENT *current) } } +void +pop_block_command_contexts (enum command_id cmd) +{ + if (command_data(cmd).flags & CF_preformatted + || command_data(cmd).data == BLOCK_menu) + { + if (pop_context () != ct_preformatted) + fatal ("preformatted context expected"); + } + else if (command_data(cmd).data == BLOCK_format_raw) + { + if (pop_context () != ct_rawpreformatted) + fatal ("rawpreformatted context expected"); + } + else if (cmd == CM_displaymath) + { + if (pop_context () != ct_math) + fatal ("math context expected"); + } + else if (command_data(cmd).data == BLOCK_region) + { + pop_region (); + } +} + ELEMENT * close_current (ELEMENT *current, - enum command_id closed_command, + enum command_id closed_block_command, enum command_id interrupting_command) { /* Element is a command */ @@ -249,19 +272,27 @@ close_current (ELEMENT *current, if (command_flags(current) & CF_brace) { if (command_data(current->cmd).data == BRACE_context) - pop_context (); - current = close_brace_command (current, - closed_command, interrupting_command); + { + if (current->cmd == CM_math) + { + if (pop_context () != ct_math) + fatal ("math context expected"); + } + else if (pop_context () != ct_brace_command) + fatal ("context brace command context expected"); + } + current = close_brace_command (current, closed_block_command, + interrupting_command); } else if (command_flags(current) & CF_block) { enum command_id cmd = current->cmd; ELEMENT *parent = 0; - if (closed_command) + if (closed_block_command) { line_error ("`@end' expected `%s', but saw `%s'", command_name(current->cmd), - command_name(closed_command)); + command_name(closed_block_command)); } else if (interrupting_command) { @@ -282,15 +313,7 @@ close_current (ELEMENT *current, (parent)); } } - if (command_data(cmd).flags - & (CF_preformatted | CF_menu | CF_format_raw)) - { - pop_context (); - } - if (command_data(cmd).data == BLOCK_region) - { - pop_region (); - } + pop_block_command_contexts (cmd); if (!parent) parent = current->parent; current = parent; @@ -312,7 +335,7 @@ close_current (ELEMENT *current, command_error (current, "misplaced {"); if (current->contents.number > 0 && current->contents.list[0]->type - == ET_empty_spaces_before_argument) + == ET_internal_spaces_before_argument) { /* remove spaces element from tree and update extra values */ abort_empty_line (¤t, 0); @@ -322,10 +345,6 @@ close_current (ELEMENT *current, break; case ET_menu_comment: case ET_menu_entry_description: - c = pop_context (); - if (c != ct_preformatted) - fatal ("preformatted context expected"); - /* Remove empty menu_comment */ if (current->type == ET_menu_comment && current->contents.number == 0) @@ -362,64 +381,42 @@ close_current (ELEMENT *current, return current; } -/* Return lowest level ancestor of CURRENT containing a CLOSED_COMMAND - element. Set CLOSED_ELEMENT to the element itself. INTERRUPTING is used in +/* Return lowest level ancestor of CURRENT containing a CLOSED_BLOCK_COMMAND + element, or the lowest level ancestor if CLOSED_BLOCK_COMMAND is 0. + Set CLOSED_BLOCK_ELEMENT to the last closed element. INTERRUPTING is used in close_brace_command to display an error message. Remove a context from - context stack if it was added by this command. */ + context stack if CLOSED_BLOCK_COMMAND is not 0 and a context was added + by the CLOSED_BLOCK_COMMAND. + CLOSED_BLOCK_COMMAND should be the id of a block command. + */ ELEMENT * -close_commands (ELEMENT *current, enum command_id closed_command, +close_commands (ELEMENT *current, enum command_id closed_block_command, ELEMENT **closed_element, enum command_id interrupting) { *closed_element = 0; - current = end_paragraph (current, closed_command, interrupting); - current = end_preformatted (current, closed_command, interrupting); + current = end_paragraph (current, closed_block_command, interrupting); + current = end_preformatted (current, closed_block_command, interrupting); while (current->parent - && (!closed_command || current->cmd != closed_command) + && (!closed_block_command || current->cmd != closed_block_command) /* Stop if in a root command. */ - && !(current->cmd && command_flags(current) & CF_root)) + && !(current->cmd && command_flags(current) & CF_root) + /* Stop if at a type at the root */ + && !(current->type == ET_before_node_section)) { close_command_cleanup (current); - current = close_current (current, closed_command, interrupting); + current = close_current (current, closed_block_command, interrupting); } - if (closed_command && current->cmd == closed_command) + if (closed_block_command && current->cmd == closed_block_command) { - if (command_data(current->cmd).flags & CF_preformatted) - { - if (pop_context () != ct_preformatted) - fatal ("preformatted context expected"); - } - else if (command_data(current->cmd).flags & CF_format_raw) - { - if (pop_context () != ct_rawpreformatted) - fatal ("rawpreformatted context expected"); - // TODO: pop expanded formats stack - } - else if (command_data(current->cmd).flags & CF_menu) - { - enum context c; - c = pop_context (); - if (c != ct_menu && c != ct_preformatted) - fatal ("menu or preformatted context expected"); - } - else if (current->cmd == CM_math || current->cmd == CM_displaymath) - { - enum context c; - c = pop_context (); - if (c != ct_math) - fatal ("math context expected"); - } - - if (command_data(current->cmd).data == BLOCK_region) - pop_region (); - + pop_block_command_contexts (current->cmd); *closed_element = current; current = current->parent; } - else if (closed_command) + else if (closed_block_command) { - line_error ("unmatched `@end %s'", command_name(closed_command)); + line_error ("unmatched `@end %s'", command_name(closed_block_command)); } return current; diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_data.awk b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_data.awk index 9974d1aefb..133a1c044e 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_data.awk +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_data.awk @@ -118,12 +118,13 @@ BEGIN { } commands[c] = $2 data[c] = $3 + args_nr[c] = $4 } END { print "COMMAND builtin_command_data[] = {" > CD - print "0, 0, 0," > CD + print "0, 0, 0, 0," > CD # We want the output sorted so we can use bsearch PROCINFO["sorted_in"]="@ind_str_asc" @@ -152,7 +153,30 @@ END { } else { command_data = "0" } - print "\"" c2 "\", " flags ", " command_data "," > CD + + if (args_nr[c] != "") { + args_nr_data = args_nr[c] + } else { + # backward compatibility, remove when updated + where_digit = match(data[c], /^[0-9]$/) + if (where_digit != 0) { + args_nr_data = data[c] + } else { + where = 0 + if (commands[c] != "") { + where = match(commands[c], /block/) + if (where == 0) { + where = match(commands[c], /^nobrace$/) + } + } + if (where != 0 || command_data == "BRACE_noarg") { + args_nr_data = "0" + } else { + args_nr_data = "1" + } + } + } + print "\"" c2 "\", " flags ", " command_data ", " args_nr_data "," > CD } print "};" > CD print "};" > CI diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_data.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_data.c index 7d0e5a0976..19a2a22cf2 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_data.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_data.c @@ -1,362 +1,370 @@ COMMAND builtin_command_data[] = { -0, 0, 0, -"\t", CF_nobrace, 0, -"\n", CF_nobrace, 0, -"\x20", CF_nobrace, 0, -"!", CF_nobrace, 0, -"\"", CF_brace | CF_accent, BRACE_accent, -"&", CF_nobrace, 0, -"'", CF_brace | CF_accent, BRACE_accent, -"*", CF_nobrace, 0, -",", CF_brace | CF_accent, BRACE_accent, -"-", CF_nobrace, 0, -".", CF_nobrace, 0, -"/", CF_nobrace, 0, -":", CF_nobrace, 0, -"=", CF_brace | CF_accent, BRACE_accent, -"?", CF_nobrace, 0, -"@", CF_nobrace, 0, -"AA", CF_brace, 0, -"AE", CF_brace, 0, -"DH", CF_brace, 0, -"H", CF_brace | CF_accent, BRACE_accent, -"L", CF_brace, 0, -"LaTeX", CF_brace, 0, -"O", CF_brace, 0, -"OE", CF_brace, 0, -"TH", CF_brace, 0, -"TeX", CF_brace, 0, -"U", CF_brace, 1, -"\\", CF_nobrace, 0, -"^", CF_brace | CF_accent, BRACE_accent, -"`", CF_brace | CF_accent, BRACE_accent, -"aa", CF_brace, 0, -"abbr", CF_brace, 2, -"acronym", CF_brace, 2, -"ae", CF_brace, 0, -"afivepaper", CF_line, LINE_skipline, -"afourlatex", CF_line, LINE_skipline, -"afourpaper", CF_line, LINE_skipline, -"afourwide", CF_line, LINE_skipline, -"alias", CF_line, 2, -"allowcodebreaks", CF_line | CF_global, 1, -"ampchar", CF_brace, 0, -"anchor", CF_brace, 1, -"appendix", CF_root | CF_line | CF_sectioning, LINE_line, -"appendixsec", CF_root | CF_line | CF_sectioning, LINE_line, -"appendixsection", CF_root | CF_line | CF_sectioning, LINE_line, -"appendixsubsec", CF_root | CF_line | CF_sectioning, LINE_line, -"appendixsubsubsec", CF_root | CF_line | CF_sectioning, LINE_line, -"arrow", CF_brace, 0, -"asis", CF_brace, BRACE_style, -"atchar", CF_brace, 0, -"author", CF_line | CF_global, LINE_line, -"b", CF_brace, BRACE_style, -"backslashchar", CF_brace, 0, -"bsixpaper", CF_line, LINE_skipline, -"bullet", CF_brace, 0, -"bye", CF_line, LINE_skipline, -"c", CF_line, LINE_lineraw, -"caption", CF_brace, BRACE_context, -"cartouche", CF_block, 0, -"center", CF_line, LINE_line, -"centerchap", CF_root | CF_line | CF_sectioning | CF_deprecated, LINE_line, -"chapheading", CF_line | CF_sectioning, LINE_line, -"chapter", CF_root | CF_line | CF_sectioning, LINE_line, -"cite", CF_brace, BRACE_style, -"clear", CF_line, LINE_special, -"click", CF_brace, 0, -"clicksequence", CF_brace, BRACE_style, -"clickstyle", CF_line | CF_global, LINE_special, -"code", CF_brace | CF_code_style, BRACE_style, -"codequotebacktick", CF_line | CF_global, 1, -"codequoteundirected", CF_line | CF_global, 1, -"columnfractions", CF_line, 1, -"comma", CF_brace, 0, -"command", CF_brace | CF_code_style, BRACE_style, -"comment", CF_line, LINE_lineraw, -"contents", CF_line | CF_global, LINE_skipline, -"copying", CF_block | CF_global_unique, BLOCK_region, -"copyright", CF_brace, 0, -"defcodeindex", CF_line, 1, -"defcv", CF_block | CF_def, 0, -"defcvx", CF_line | CF_def, LINE_line, -"deffn", CF_block | CF_def, 0, -"deffnx", CF_line | CF_def, LINE_line, -"defindex", CF_line, 1, -"definfoenclose", CF_line | CF_deprecated, 3, -"defivar", CF_block | CF_def | CF_def_alias, 0, -"defivarx", CF_line | CF_def | CF_def_alias, LINE_line, -"defmac", CF_block | CF_def | CF_def_alias, 0, -"defmacx", CF_line | CF_def | CF_def_alias, LINE_line, -"defmethod", CF_block | CF_def | CF_def_alias, 0, -"defmethodx", CF_line | CF_def | CF_def_alias, LINE_line, -"defop", CF_block | CF_def, 0, -"defopt", CF_block | CF_def | CF_def_alias, 0, -"defoptx", CF_line | CF_def | CF_def_alias, LINE_line, -"defopx", CF_line | CF_def, LINE_line, -"defspec", CF_block | CF_def | CF_def_alias, 0, -"defspecx", CF_line | CF_def | CF_def_alias, LINE_line, -"deftp", CF_block | CF_def, 0, -"deftpx", CF_line | CF_def, LINE_line, -"deftypecv", CF_block | CF_def, 0, -"deftypecvx", CF_line | CF_def, LINE_line, -"deftypefn", CF_block | CF_def, 0, -"deftypefnnewline", CF_line | CF_global, 1, -"deftypefnx", CF_line | CF_def, LINE_line, -"deftypefun", CF_block | CF_def | CF_def_alias, 0, -"deftypefunx", CF_line | CF_def | CF_def_alias, LINE_line, -"deftypeivar", CF_block | CF_def | CF_def_alias, 0, -"deftypeivarx", CF_line | CF_def | CF_def_alias, LINE_line, -"deftypemethod", CF_block | CF_def | CF_def_alias, 0, -"deftypemethodx", CF_line | CF_def | CF_def_alias, LINE_line, -"deftypeop", CF_block | CF_def, 0, -"deftypeopx", CF_line | CF_def, LINE_line, -"deftypevar", CF_block | CF_def | CF_def_alias, 0, -"deftypevarx", CF_line | CF_def | CF_def_alias, LINE_line, -"deftypevr", CF_block | CF_def, 0, -"deftypevrx", CF_line | CF_def, LINE_line, -"defun", CF_block | CF_def | CF_def_alias, 0, -"defunx", CF_line | CF_def | CF_def_alias, LINE_line, -"defvar", CF_block | CF_def | CF_def_alias, 0, -"defvarx", CF_line | CF_def | CF_def_alias, LINE_line, -"defvr", CF_block | CF_def, 0, -"defvrx", CF_line | CF_def, LINE_line, -"detailmenu", CF_block | CF_menu | CF_global, 0, -"dfn", CF_brace, BRACE_style, -"dh", CF_brace, 0, -"dircategory", CF_line, LINE_line, -"direntry", CF_block | CF_menu, 0, -"display", CF_block | CF_preformatted, 0, -"displaymath", CF_block, 0, -"dmn", CF_brace, 1, -"docbook", CF_block | CF_format_raw, 0, -"documentdescription", CF_block | CF_global_unique, BLOCK_region, -"documentencoding", CF_line | CF_global, LINE_text, -"documentlanguage", CF_line | CF_global, LINE_text, -"dotaccent", CF_brace | CF_accent, BRACE_accent, -"dotless", CF_brace | CF_accent, BRACE_accent, -"dots", CF_brace, 0, -"email", CF_brace, 2, -"emph", CF_brace, BRACE_style, -"end", CF_line, LINE_text, -"enddots", CF_brace, 0, -"enumerate", CF_block | CF_blockitem, 1, -"env", CF_brace | CF_code_style, BRACE_style, -"equiv", CF_brace, 0, -"error", CF_brace, 0, -"errormsg", CF_brace, 1, -"euro", CF_brace, 0, -"evenfooting", CF_line | CF_global_unique, LINE_lineraw, -"evenfootingmarks", CF_line | CF_global_unique, 1, -"evenheading", CF_line | CF_global_unique, LINE_lineraw, -"evenheadingmarks", CF_line | CF_global_unique, 1, -"everyfooting", CF_line | CF_global_unique, LINE_lineraw, -"everyfootingmarks", CF_line | CF_global_unique, 1, -"everyheading", CF_line | CF_global_unique, LINE_lineraw, -"everyheadingmarks", CF_line | CF_global_unique, 1, -"example", CF_block | CF_preformatted | CF_preformatted_code, BLOCK_variadic, -"exampleindent", CF_line | CF_global, 1, -"exclamdown", CF_brace, 0, -"exdent", CF_line, LINE_line, -"expansion", CF_brace, 0, -"file", CF_brace | CF_code_style, BRACE_style, -"finalout", CF_line, LINE_skipline, -"firstparagraphindent", CF_line | CF_global, 1, -"float", CF_block, 2, -"flushleft", CF_block, 0, -"flushright", CF_block, 0, -"fonttextsize", CF_line | CF_global_unique, 1, -"footnote", CF_brace | CF_global, BRACE_context, -"footnotestyle", CF_line | CF_global_unique, 1, -"format", CF_block | CF_preformatted, 0, -"frenchspacing", CF_line | CF_global, 1, -"ftable", CF_block | CF_blockitem, 1, -"geq", CF_brace, 0, -"group", CF_block, 0, -"guillemetleft", CF_brace, 0, -"guillemetright", CF_brace, 0, -"guillemotleft", CF_brace, 0, -"guillemotright", CF_brace, 0, -"guilsinglleft", CF_brace, 0, -"guilsinglright", CF_brace, 0, -"hashchar", CF_brace, 0, -"heading", CF_line | CF_sectioning, LINE_line, -"headings", CF_line | CF_global, 1, -"headitem", CF_other, OTHER_skipspace, -"headitemfont", CF_brace, BRACE_style, -"html", CF_block | CF_format_raw, 0, -"hyphenation", CF_brace | CF_global, BRACE_other, -"i", CF_brace, BRACE_style, -"ifclear", CF_block, BLOCK_conditional, -"ifcommanddefined", CF_block, BLOCK_conditional, -"ifcommandnotdefined", CF_block, BLOCK_conditional, -"ifdocbook", CF_block, BLOCK_conditional, -"ifhtml", CF_block, BLOCK_conditional, -"ifinfo", CF_block, BLOCK_conditional, -"ifnotdocbook", CF_block, BLOCK_conditional, -"ifnothtml", CF_block, BLOCK_conditional, -"ifnotinfo", CF_block, BLOCK_conditional, -"ifnotplaintext", CF_block, BLOCK_conditional, -"ifnottex", CF_block, BLOCK_conditional, -"ifnotxml", CF_block, BLOCK_conditional, -"ifplaintext", CF_block, BLOCK_conditional, -"ifset", CF_block, BLOCK_conditional, -"iftex", CF_block, BLOCK_conditional, -"ifxml", CF_block, BLOCK_conditional, -"ignore", CF_block, BLOCK_raw, -"image", CF_brace, 5, -"include", CF_line, LINE_text, -"indent", CF_other, OTHER_skipspace, -"indentedblock", CF_block, 0, -"indicateurl", CF_brace | CF_code_style, 1, -"inforef", CF_brace | CF_ref | CF_deprecated, 3, -"inlinefmt", CF_brace | CF_inline, 2, -"inlinefmtifelse", CF_brace | CF_inline, 3, -"inlineifclear", CF_brace | CF_inline, 2, -"inlineifset", CF_brace | CF_inline, 2, -"inlineraw", CF_brace | CF_inline, 2, -"insertcopying", CF_line | CF_global, LINE_skipline, -"item", CF_other, OTHER_skipspace, -"item_LINE", CF_line, LINE_line, -"itemize", CF_block | CF_blockitem, 1, -"itemx", CF_line, LINE_line, -"kbd", CF_brace | CF_code_style, BRACE_style, -"kbdinputstyle", CF_line | CF_global, 1, -"key", CF_brace, BRACE_other, -"l", CF_brace, 0, -"lbracechar", CF_brace, 0, -"leq", CF_brace, 0, -"lisp", CF_block | CF_preformatted | CF_preformatted_code, 0, -"listoffloats", CF_line | CF_global, LINE_line, -"lowersections", CF_line, LINE_skipline, -"macro", CF_block, BLOCK_raw, -"majorheading", CF_line | CF_sectioning, LINE_line, -"math", CF_brace, BRACE_context, -"menu", CF_block | CF_menu, 0, -"minus", CF_brace, 0, -"multitable", CF_block | CF_blockitem, BLOCK_multitable, -"need", CF_line, 1, -"node", CF_root | CF_line, LINE_line, -"noindent", CF_other, OTHER_skipspace, -"novalidate", CF_line | CF_global_unique, LINE_skipline, -"o", CF_brace, 0, -"oddfooting", CF_line | CF_global_unique, LINE_lineraw, -"oddfootingmarks", CF_line | CF_global_unique, 1, -"oddheading", CF_line | CF_global_unique, LINE_lineraw, -"oddheadingmarks", CF_line | CF_global_unique, 1, -"oe", CF_brace, 0, -"ogonek", CF_brace | CF_accent, BRACE_accent, -"option", CF_brace | CF_code_style, BRACE_style, -"ordf", CF_brace, 0, -"ordm", CF_brace, 0, -"page", CF_line, LINE_skipline, -"pagesizes", CF_line | CF_global_unique, LINE_line, -"paragraphindent", CF_line | CF_global, 1, -"part", CF_root | CF_line | CF_sectioning | CF_global, LINE_line, -"point", CF_brace, 0, -"pounds", CF_brace, 0, -"print", CF_brace, 0, -"printindex", CF_line | CF_global, 1, -"pxref", CF_brace | CF_ref, 5, -"questiondown", CF_brace, 0, -"quotation", CF_block, 1, -"quotedblbase", CF_brace, 0, -"quotedblleft", CF_brace, 0, -"quotedblright", CF_brace, 0, -"quoteleft", CF_brace, 0, -"quoteright", CF_brace, 0, -"quotesinglbase", CF_brace, 0, -"r", CF_brace, BRACE_style, -"raggedright", CF_block, 0, -"raisesections", CF_line, LINE_skipline, -"rbracechar", CF_brace, 0, -"ref", CF_brace | CF_ref, 5, -"refill", CF_other | CF_deprecated, OTHER_noarg, -"registeredsymbol", CF_brace, 0, -"result", CF_brace, 0, -"ringaccent", CF_brace | CF_accent, BRACE_accent, -"rmacro", CF_block, BLOCK_raw, -"samp", CF_brace | CF_code_style, BRACE_style, -"sansserif", CF_brace, BRACE_style, -"sc", CF_brace, BRACE_style, -"section", CF_root | CF_line | CF_sectioning, LINE_line, -"seealso", CF_brace, 1, -"seeentry", CF_brace, 1, -"set", CF_line, LINE_special, -"setchapternewpage", CF_line | CF_global_unique, 1, -"setfilename", CF_line | CF_global_unique, LINE_text, -"settitle", CF_line | CF_global_unique, LINE_line, -"shortcaption", CF_brace, BRACE_context, -"shortcontents", CF_line | CF_global, LINE_skipline, -"shorttitlepage", CF_line | CF_global_unique, LINE_line, -"slanted", CF_brace, BRACE_style, -"smallbook", CF_line, LINE_skipline, -"smalldisplay", CF_block | CF_preformatted, 0, -"smallexample", CF_block | CF_preformatted | CF_preformatted_code, 0, -"smallformat", CF_block | CF_preformatted, 0, -"smallindentedblock", CF_block, 0, -"smalllisp", CF_block | CF_preformatted | CF_preformatted_code, 0, -"smallquotation", CF_block, 1, -"sortas", CF_brace, 1, -"sp", CF_line, 1, -"ss", CF_brace, 0, -"strong", CF_brace, BRACE_style, -"sub", CF_brace, BRACE_style, -"subentry", CF_line, LINE_line, -"subheading", CF_line | CF_sectioning, LINE_line, -"subsection", CF_root | CF_line | CF_sectioning, LINE_line, -"subsubheading", CF_line | CF_sectioning, LINE_line, -"subsubsection", CF_root | CF_line | CF_sectioning, LINE_line, -"subtitle", CF_line | CF_global, LINE_line, -"summarycontents", CF_line | CF_global, LINE_skipline, -"sup", CF_brace, BRACE_style, -"syncodeindex", CF_line, 2, -"synindex", CF_line, 2, -"t", CF_brace | CF_code_style, BRACE_other, -"tab", CF_other, OTHER_skipspace, -"table", CF_block | CF_blockitem, 1, -"tex", CF_block | CF_format_raw, 0, -"textdegree", CF_brace, 0, -"th", CF_brace, 0, -"thischapter", CF_other | CF_in_heading, OTHER_noarg, -"thischaptername", CF_other | CF_in_heading, OTHER_noarg, -"thischapternum", CF_other | CF_in_heading, OTHER_noarg, -"thisfile", CF_other | CF_in_heading, OTHER_noarg, -"thispage", CF_other | CF_in_heading, OTHER_noarg, -"thistitle", CF_other | CF_in_heading, OTHER_noarg, -"tie", CF_brace, 0, -"tieaccent", CF_brace | CF_accent, BRACE_accent, -"title", CF_line | CF_global_unique, LINE_line, -"titlefont", CF_brace | CF_global, 1, -"titlepage", CF_block | CF_global_unique, BLOCK_region, -"today", CF_brace, 0, -"top", CF_root | CF_line | CF_sectioning | CF_global_unique, LINE_line, -"u", CF_brace | CF_accent, BRACE_accent, -"ubaraccent", CF_brace | CF_accent, BRACE_accent, -"udotaccent", CF_brace | CF_accent, BRACE_accent, -"unmacro", CF_line, LINE_special, -"unnumbered", CF_root | CF_line | CF_sectioning, LINE_line, -"unnumberedsec", CF_root | CF_line | CF_sectioning, LINE_line, -"unnumberedsubsec", CF_root | CF_line | CF_sectioning, LINE_line, -"unnumberedsubsubsec", CF_root | CF_line | CF_sectioning, LINE_line, -"uref", CF_brace, 3, -"urefbreakstyle", CF_line | CF_global, 1, -"url", CF_brace, 3, -"v", CF_brace | CF_accent, BRACE_accent, -"value", CF_brace, 0, -"var", CF_brace, BRACE_style, -"verb", CF_brace | CF_code_style, BRACE_other, -"verbatim", CF_block, BLOCK_raw, -"verbatiminclude", CF_line, LINE_text, -"vskip", CF_line, LINE_lineraw, -"vtable", CF_block | CF_blockitem, 1, -"w", CF_brace, BRACE_other, -"xml", CF_block | CF_format_raw, 0, -"xref", CF_brace | CF_ref, 5, -"xrefautomaticsectiontitle", CF_line | CF_global, 1, -"{", CF_nobrace, 0, -"|", CF_nobrace, 0, -"}", CF_nobrace, 0, -"~", CF_brace | CF_accent, BRACE_accent, +0, 0, 0, 0, +"\t", CF_nobrace, NOBRACE_symbol, 0, +"\n", CF_nobrace, NOBRACE_symbol, 0, +"\x20", CF_nobrace, NOBRACE_symbol, 0, +"!", CF_nobrace, NOBRACE_symbol, 0, +"\"", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"&", CF_nobrace, NOBRACE_symbol, 0, +"'", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"*", CF_nobrace, NOBRACE_symbol, 0, +",", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"-", CF_nobrace, NOBRACE_symbol, 0, +".", CF_nobrace, NOBRACE_symbol, 0, +"/", CF_nobrace, NOBRACE_symbol, 0, +":", CF_nobrace, NOBRACE_symbol, 0, +"=", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"?", CF_nobrace, NOBRACE_symbol, 0, +"@", CF_nobrace, NOBRACE_symbol, 0, +"AA", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"AE", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"DH", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"H", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"L", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"LaTeX", CF_brace, BRACE_noarg, 0, +"O", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"OE", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"TH", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"TeX", CF_brace, BRACE_noarg, 0, +"U", CF_brace, BRACE_arguments, 1, +"\\", CF_nobrace, NOBRACE_symbol, 0, +"^", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"`", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"aa", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"abbr", CF_brace | CF_contain_simple_text, BRACE_arguments, 2, +"acronym", CF_brace | CF_contain_simple_text, BRACE_arguments, 2, +"ae", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"afivepaper", CF_line | CF_global_unique, LINE_skipline, 1, +"afourlatex", CF_line | CF_global_unique, LINE_skipline, 1, +"afourpaper", CF_line | CF_global_unique, LINE_skipline, 1, +"afourwide", CF_line | CF_global_unique, LINE_skipline, 1, +"alias", CF_line | CF_contain_plain_text, LINE_specific, 2, +"allowcodebreaks", CF_line | CF_global | CF_contain_plain_text, LINE_specific, 1, +"ampchar", CF_brace, BRACE_noarg, 0, +"anchor", CF_brace | CF_contain_simple_text, BRACE_arguments, 1, +"appendix", CF_line | CF_root | CF_sectioning_heading, LINE_line, 1, +"appendixsec", CF_line | CF_root | CF_sectioning_heading, LINE_line, 1, +"appendixsection", CF_line | CF_root | CF_sectioning_heading, LINE_line, 1, +"appendixsubsec", CF_line | CF_root | CF_sectioning_heading, LINE_line, 1, +"appendixsubsubsec", CF_line | CF_root | CF_sectioning_heading, LINE_line, 1, +"arrow", CF_brace, BRACE_noarg, 0, +"asis", CF_brace, BRACE_style_other, 1, +"atchar", CF_brace, BRACE_noarg, 0, +"author", CF_line | CF_global | CF_contain_simple_text, LINE_line, 1, +"b", CF_brace, BRACE_style_other, 1, +"backslashchar", CF_brace, BRACE_noarg, 0, +"bsixpaper", CF_line | CF_global_unique, LINE_skipline, 1, +"bullet", CF_brace, BRACE_noarg, 0, +"bye", CF_line, LINE_skipline, 1, +"c", CF_line, LINE_lineraw, 1, +"caption", CF_brace | CF_close_paragraph, BRACE_context, 1, +"cartouche", CF_block | CF_close_paragraph, 0, 0, +"center", CF_line | CF_close_paragraph, LINE_line, 1, +"centerchap", CF_line | CF_root | CF_sectioning_heading | CF_deprecated, LINE_line, 1, +"chapheading", CF_line | CF_sectioning_heading | CF_close_paragraph, LINE_line, 1, +"chapter", CF_line | CF_root | CF_sectioning_heading, LINE_line, 1, +"cite", CF_brace, BRACE_style_other, 1, +"clear", CF_line, LINE_special, 1, +"click", CF_brace, BRACE_noarg, 0, +"clicksequence", CF_brace, BRACE_style_other, 1, +"clickstyle", CF_line | CF_global, LINE_special, 1, +"code", CF_brace, BRACE_style_code, 1, +"codequotebacktick", CF_line | CF_global | CF_contain_plain_text, LINE_specific, 1, +"codequoteundirected", CF_line | CF_global | CF_contain_plain_text, LINE_specific, 1, +"columnfractions", CF_line | CF_contain_plain_text, LINE_specific, 1, +"comma", CF_brace, BRACE_noarg, 0, +"command", CF_brace, BRACE_style_code, 1, +"comment", CF_line, LINE_lineraw, 1, +"contents", CF_line | CF_close_paragraph | CF_global, LINE_skipline, 1, +"copying", CF_block | CF_close_paragraph | CF_global_unique, BLOCK_region, 0, +"copyright", CF_brace, BRACE_noarg, 0, +"defcodeindex", CF_line | CF_contain_plain_text, LINE_specific, 1, +"defcv", CF_block | CF_def | CF_close_paragraph, BLOCK_def, 0, +"defcvx", CF_line | CF_def | CF_close_paragraph, LINE_line, 1, +"deffn", CF_block | CF_def | CF_close_paragraph, BLOCK_def, 0, +"deffnx", CF_line | CF_def | CF_close_paragraph, LINE_line, 1, +"defindex", CF_line | CF_contain_plain_text, LINE_specific, 1, +"definfoenclose", CF_line | CF_contain_plain_text | CF_deprecated, LINE_specific, 3, +"defivar", CF_block | CF_def | CF_def_alias | CF_close_paragraph, BLOCK_def, 0, +"defivarx", CF_line | CF_def | CF_def_alias | CF_close_paragraph, LINE_line, 1, +"defmac", CF_block | CF_def | CF_def_alias | CF_close_paragraph, BLOCK_def, 0, +"defmacx", CF_line | CF_def | CF_def_alias | CF_close_paragraph, LINE_line, 1, +"defmethod", CF_block | CF_def | CF_def_alias | CF_close_paragraph, BLOCK_def, 0, +"defmethodx", CF_line | CF_def | CF_def_alias | CF_close_paragraph, LINE_line, 1, +"defop", CF_block | CF_def | CF_close_paragraph, BLOCK_def, 0, +"defopt", CF_block | CF_def | CF_def_alias | CF_close_paragraph, BLOCK_def, 0, +"defoptx", CF_line | CF_def | CF_def_alias | CF_close_paragraph, LINE_line, 1, +"defopx", CF_line | CF_def | CF_close_paragraph, LINE_line, 1, +"defspec", CF_block | CF_def | CF_def_alias | CF_close_paragraph, BLOCK_def, 0, +"defspecx", CF_line | CF_def | CF_def_alias | CF_close_paragraph, LINE_line, 1, +"deftp", CF_block | CF_def | CF_close_paragraph, BLOCK_def, 0, +"deftpx", CF_line | CF_def | CF_close_paragraph, LINE_line, 1, +"deftypecv", CF_block | CF_def | CF_close_paragraph, BLOCK_def, 0, +"deftypecvx", CF_line | CF_def | CF_close_paragraph, LINE_line, 1, +"deftypefn", CF_block | CF_def | CF_close_paragraph, BLOCK_def, 0, +"deftypefnnewline", CF_line | CF_global | CF_contain_plain_text, LINE_specific, 1, +"deftypefnx", CF_line | CF_def | CF_close_paragraph, LINE_line, 1, +"deftypefun", CF_block | CF_def | CF_def_alias | CF_close_paragraph, BLOCK_def, 0, +"deftypefunx", CF_line | CF_def | CF_def_alias | CF_close_paragraph, LINE_line, 1, +"deftypeivar", CF_block | CF_def | CF_def_alias | CF_close_paragraph, BLOCK_def, 0, +"deftypeivarx", CF_line | CF_def | CF_def_alias | CF_close_paragraph, LINE_line, 1, +"deftypemethod", CF_block | CF_def | CF_def_alias | CF_close_paragraph, BLOCK_def, 0, +"deftypemethodx", CF_line | CF_def | CF_def_alias | CF_close_paragraph, LINE_line, 1, +"deftypeop", CF_block | CF_def | CF_close_paragraph, BLOCK_def, 0, +"deftypeopx", CF_line | CF_def | CF_close_paragraph, LINE_line, 1, +"deftypevar", CF_block | CF_def | CF_def_alias | CF_close_paragraph, BLOCK_def, 0, +"deftypevarx", CF_line | CF_def | CF_def_alias | CF_close_paragraph, LINE_line, 1, +"deftypevr", CF_block | CF_def | CF_close_paragraph, BLOCK_def, 0, +"deftypevrx", CF_line | CF_def | CF_close_paragraph, LINE_line, 1, +"defun", CF_block | CF_def | CF_def_alias | CF_close_paragraph, BLOCK_def, 0, +"defunx", CF_line | CF_def | CF_def_alias | CF_close_paragraph, LINE_line, 1, +"defvar", CF_block | CF_def | CF_def_alias | CF_close_paragraph, BLOCK_def, 0, +"defvarx", CF_line | CF_def | CF_def_alias | CF_close_paragraph, LINE_line, 1, +"defvr", CF_block | CF_def | CF_close_paragraph, BLOCK_def, 0, +"defvrx", CF_line | CF_def | CF_close_paragraph, LINE_line, 1, +"detailmenu", CF_block | CF_close_paragraph | CF_global, BLOCK_menu, 0, +"dfn", CF_brace, BRACE_style_other, 1, +"dh", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"dircategory", CF_line | CF_close_paragraph | CF_contain_simple_text, LINE_line, 1, +"direntry", CF_block | CF_close_paragraph, BLOCK_menu, 0, +"display", CF_block | CF_close_paragraph | CF_preformatted, BLOCK_preformatted, 0, +"displaymath", CF_block | CF_close_paragraph | CF_math, BLOCK_math, 0, +"dmn", CF_brace | CF_contain_plain_text, BRACE_other, 1, +"docbook", CF_block, BLOCK_format_raw, 0, +"documentdescription", CF_block | CF_close_paragraph | CF_global_unique, BLOCK_region, 0, +"documentencoding", CF_line | CF_global | CF_contain_plain_text, LINE_text, 1, +"documentlanguage", CF_line | CF_global | CF_contain_plain_text | CF_contain_plain_text, LINE_text, 1, +"dotaccent", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"dotless", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"dots", CF_brace, BRACE_noarg, 0, +"email", CF_brace | CF_contain_simple_text, BRACE_arguments, 2, +"emph", CF_brace, BRACE_style_other, 1, +"end", CF_line | CF_contain_plain_text, LINE_text, 1, +"enddots", CF_brace, BRACE_noarg, 0, +"enumerate", CF_block | CF_close_paragraph | CF_blockitem | CF_contain_simple_text, BLOCK_item_container, 1, +"env", CF_brace, BRACE_style_code, 1, +"equiv", CF_brace, BRACE_noarg, 0, +"error", CF_brace, BRACE_noarg, 0, +"errormsg", CF_brace | CF_contain_simple_text, BRACE_arguments, 1, +"euro", CF_brace, BRACE_noarg, 0, +"evenfooting", CF_line | CF_global | CF_heading_spec | CF_contain_simple_text, LINE_line, 1, +"evenfootingmarks", CF_line | CF_global_unique | CF_contain_plain_text, LINE_specific, 1, +"evenheading", CF_line | CF_global | CF_heading_spec | CF_contain_simple_text, LINE_line, 1, +"evenheadingmarks", CF_line | CF_global_unique | CF_contain_plain_text, LINE_specific, 1, +"everyfooting", CF_line | CF_global | CF_heading_spec | CF_contain_simple_text, LINE_line, 1, +"everyfootingmarks", CF_line | CF_global_unique | CF_contain_plain_text, LINE_specific, 1, +"everyheading", CF_line | CF_global | CF_heading_spec | CF_contain_simple_text, LINE_line, 1, +"everyheadingmarks", CF_line | CF_global_unique | CF_contain_plain_text, LINE_specific, 1, +"example", CF_block | CF_close_paragraph | CF_preformatted | CF_preformatted_code | CF_variadic | CF_contain_simple_text, BLOCK_preformatted, 0, +"exampleindent", CF_line | CF_global | CF_contain_plain_text, LINE_specific, 1, +"exclamdown", CF_brace, BRACE_noarg, 0, +"exdent", CF_line | CF_close_paragraph, LINE_line, 1, +"expansion", CF_brace, BRACE_noarg, 0, +"file", CF_brace, BRACE_style_code, 1, +"finalout", CF_line, LINE_skipline, 1, +"firstparagraphindent", CF_line | CF_global | CF_contain_plain_text, LINE_specific, 1, +"float", CF_block | CF_close_paragraph | CF_contain_simple_text, BLOCK_float, 2, +"flushleft", CF_block | CF_close_paragraph, 0, 0, +"flushright", CF_block | CF_close_paragraph, 0, 0, +"fonttextsize", CF_line | CF_global_unique | CF_contain_plain_text, LINE_specific, 1, +"footnote", CF_brace | CF_global, BRACE_context, 1, +"footnotestyle", CF_line | CF_global_unique | CF_contain_plain_text, LINE_specific, 1, +"format", CF_block | CF_close_paragraph | CF_preformatted, BLOCK_preformatted, 0, +"frenchspacing", CF_line | CF_global | CF_contain_plain_text, LINE_specific, 1, +"ftable", CF_block | CF_close_paragraph | CF_blockitem | CF_contain_simple_text, BLOCK_item_line, 1, +"geq", CF_brace, BRACE_noarg, 0, +"group", CF_block | CF_close_paragraph, 0, 0, +"guillemetleft", CF_brace, BRACE_noarg, 0, +"guillemetright", CF_brace, BRACE_noarg, 0, +"guillemotleft", CF_brace, BRACE_noarg, 0, +"guillemotright", CF_brace, BRACE_noarg, 0, +"guilsinglleft", CF_brace, BRACE_noarg, 0, +"guilsinglright", CF_brace, BRACE_noarg, 0, +"hashchar", CF_brace, BRACE_noarg, 0, +"heading", CF_line | CF_sectioning_heading | CF_close_paragraph, LINE_line, 1, +"headings", CF_line | CF_global | CF_contain_plain_text, LINE_specific, 1, +"headitem", CF_nobrace | CF_close_paragraph, NOBRACE_skipspace, 1, +"headitemfont", CF_brace, BRACE_style_other, 1, +"html", CF_block, BLOCK_format_raw, 0, +"hyphenation", CF_brace | CF_global | CF_contain_plain_text, BRACE_arguments, 1, +"i", CF_brace, BRACE_style_other, 1, +"ifclear", CF_block, BLOCK_conditional, 0, +"ifcommanddefined", CF_block, BLOCK_conditional, 0, +"ifcommandnotdefined", CF_block, BLOCK_conditional, 0, +"ifdocbook", CF_block, BLOCK_conditional, 0, +"ifhtml", CF_block, BLOCK_conditional, 0, +"ifinfo", CF_block, BLOCK_conditional, 0, +"iflatex", CF_block, BLOCK_conditional, 0, +"ifnotdocbook", CF_block, BLOCK_conditional, 0, +"ifnothtml", CF_block, BLOCK_conditional, 0, +"ifnotinfo", CF_block, BLOCK_conditional, 0, +"ifnotlatex", CF_block, BLOCK_conditional, 0, +"ifnotplaintext", CF_block, BLOCK_conditional, 0, +"ifnottex", CF_block, BLOCK_conditional, 0, +"ifnotxml", CF_block, BLOCK_conditional, 0, +"ifplaintext", CF_block, BLOCK_conditional, 0, +"ifset", CF_block, BLOCK_conditional, 0, +"iftex", CF_block, BLOCK_conditional, 0, +"ifxml", CF_block, BLOCK_conditional, 0, +"ignore", CF_block, BLOCK_raw, 0, +"image", CF_brace | CF_contain_simple_text, BRACE_arguments, 5, +"include", CF_line | CF_contain_plain_text, LINE_text, 1, +"indent", CF_nobrace, NOBRACE_skipspace, 0, +"indentedblock", CF_block | CF_close_paragraph, 0, 0, +"indicateurl", CF_brace, BRACE_style_code, 1, +"inforef", CF_brace | CF_ref | CF_contain_simple_text | CF_deprecated, BRACE_arguments, 3, +"inlinefmt", CF_brace, BRACE_inline, 2, +"inlinefmtifelse", CF_brace, BRACE_inline, 3, +"inlineifclear", CF_brace, BRACE_inline, 2, +"inlineifset", CF_brace, BRACE_inline, 2, +"inlineraw", CF_brace, BRACE_inline, 2, +"insertcopying", CF_line | CF_close_paragraph | CF_global, LINE_skipline, 1, +"item", CF_nobrace | CF_close_paragraph, NOBRACE_skipspace, 1, +"item_LINE", CF_line | CF_close_paragraph | CF_contain_simple_text, LINE_line, 1, +"itemize", CF_block | CF_close_paragraph | CF_blockitem | CF_contain_simple_text, BLOCK_item_container, 1, +"itemx", CF_line | CF_close_paragraph | CF_contain_simple_text, LINE_line, 1, +"kbd", CF_brace, BRACE_style_code, 1, +"kbdinputstyle", CF_line | CF_global | CF_contain_plain_text, LINE_specific, 1, +"key", CF_brace | CF_contain_plain_text, BRACE_style_code, 1, +"l", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"latex", CF_block, BLOCK_format_raw, 0, +"lbracechar", CF_brace, BRACE_noarg, 0, +"leq", CF_brace, BRACE_noarg, 0, +"lisp", CF_block | CF_close_paragraph | CF_preformatted | CF_preformatted_code, BLOCK_preformatted, 0, +"listoffloats", CF_line | CF_close_paragraph | CF_global | CF_contain_simple_text, LINE_line, 1, +"lowersections", CF_line, LINE_skipline, 1, +"macro", CF_block, BLOCK_raw, 0, +"majorheading", CF_line | CF_sectioning_heading | CF_close_paragraph, LINE_line, 1, +"math", CF_brace | CF_math | CF_contain_simple_text, BRACE_context, 1, +"menu", CF_block | CF_close_paragraph, BLOCK_menu, 0, +"microtype", CF_line | CF_global | CF_contain_plain_text, LINE_specific, 1, +"minus", CF_brace, BRACE_noarg, 0, +"multitable", CF_block | CF_close_paragraph | CF_blockitem | CF_contain_simple_text, BLOCK_multitable, 0, +"need", CF_line | CF_close_paragraph | CF_contain_plain_text, LINE_specific, 1, +"node", CF_line | CF_root | CF_contain_simple_text, LINE_line, 4, +"noindent", CF_nobrace, NOBRACE_skipspace, 0, +"novalidate", CF_line | CF_global_unique, LINE_skipline, 1, +"o", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"oddfooting", CF_line | CF_global | CF_heading_spec | CF_contain_simple_text, LINE_line, 1, +"oddfootingmarks", CF_line | CF_global_unique | CF_contain_plain_text, LINE_specific, 1, +"oddheading", CF_line | CF_global | CF_heading_spec | CF_contain_simple_text, LINE_line, 1, +"oddheadingmarks", CF_line | CF_global_unique | CF_contain_plain_text, LINE_specific, 1, +"oe", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"ogonek", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"option", CF_brace, BRACE_style_code, 1, +"ordf", CF_brace, BRACE_noarg, 0, +"ordm", CF_brace, BRACE_noarg, 0, +"page", CF_line | CF_close_paragraph, LINE_skipline, 1, +"pagesizes", CF_line | CF_global_unique | CF_contain_plain_text, LINE_line, 1, +"paragraphindent", CF_line | CF_global | CF_contain_plain_text, LINE_specific, 1, +"part", CF_line | CF_root | CF_sectioning_heading | CF_global, LINE_line, 1, +"point", CF_brace, BRACE_noarg, 0, +"pounds", CF_brace, BRACE_noarg, 0, +"print", CF_brace, BRACE_noarg, 0, +"printindex", CF_line | CF_close_paragraph | CF_global | CF_contain_plain_text, LINE_specific, 1, +"pxref", CF_brace | CF_ref | CF_contain_simple_text, BRACE_arguments, 5, +"questiondown", CF_brace, BRACE_noarg, 0, +"quotation", CF_block | CF_close_paragraph | CF_contain_simple_text, BLOCK_quotation, 1, +"quotedblbase", CF_brace, BRACE_noarg, 0, +"quotedblleft", CF_brace, BRACE_noarg, 0, +"quotedblright", CF_brace, BRACE_noarg, 0, +"quoteleft", CF_brace, BRACE_noarg, 0, +"quoteright", CF_brace, BRACE_noarg, 0, +"quotesinglbase", CF_brace, BRACE_noarg, 0, +"r", CF_brace, BRACE_style_no_code, 1, +"raggedright", CF_block | CF_close_paragraph, 0, 0, +"raisesections", CF_line, LINE_skipline, 1, +"rbracechar", CF_brace, BRACE_noarg, 0, +"ref", CF_brace | CF_ref | CF_contain_simple_text, BRACE_arguments, 5, +"refill", CF_nobrace | CF_deprecated, NOBRACE_other, 1, +"registeredsymbol", CF_brace, BRACE_noarg, 0, +"result", CF_brace, BRACE_noarg, 0, +"ringaccent", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"rmacro", CF_block, BLOCK_raw, 0, +"samp", CF_brace, BRACE_style_code, 1, +"sansserif", CF_brace, BRACE_style_other, 1, +"sc", CF_brace, BRACE_style_other, 1, +"section", CF_line | CF_root | CF_sectioning_heading, LINE_line, 1, +"seealso", CF_brace | CF_contain_simple_text, BRACE_arguments, 1, +"seeentry", CF_brace | CF_contain_simple_text, BRACE_arguments, 1, +"set", CF_line, LINE_special, 1, +"setchapternewpage", CF_line | CF_global_unique | CF_contain_plain_text, LINE_specific, 1, +"setfilename", CF_line | CF_close_paragraph | CF_global_unique | CF_contain_plain_text, LINE_text, 1, +"settitle", CF_line | CF_global_unique | CF_contain_simple_text, LINE_line, 1, +"shortcaption", CF_brace | CF_close_paragraph | CF_contain_simple_text, BRACE_context, 1, +"shortcontents", CF_line | CF_close_paragraph | CF_global, LINE_skipline, 1, +"shorttitlepage", CF_line | CF_global_unique | CF_contain_simple_text, LINE_line, 1, +"slanted", CF_brace, BRACE_style_other, 1, +"smallbook", CF_line | CF_global_unique, LINE_skipline, 1, +"smalldisplay", CF_block | CF_close_paragraph | CF_preformatted, BLOCK_preformatted, 0, +"smallexample", CF_block | CF_close_paragraph | CF_preformatted | CF_preformatted_code, BLOCK_preformatted, 0, +"smallformat", CF_block | CF_close_paragraph | CF_preformatted, BLOCK_preformatted, 0, +"smallindentedblock", CF_block | CF_close_paragraph, 0, 0, +"smalllisp", CF_block | CF_close_paragraph | CF_preformatted | CF_preformatted_code, BLOCK_preformatted, 0, +"smallquotation", CF_block | CF_close_paragraph | CF_contain_simple_text, BLOCK_quotation, 1, +"sortas", CF_brace | CF_contain_plain_text, BRACE_arguments, 1, +"sp", CF_line | CF_close_paragraph | CF_contain_plain_text, LINE_specific, 1, +"ss", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"strong", CF_brace, BRACE_style_other, 1, +"sub", CF_brace, BRACE_style_other, 1, +"subentry", CF_line | CF_contain_simple_text, LINE_line, 1, +"subheading", CF_line | CF_sectioning_heading | CF_close_paragraph, LINE_line, 1, +"subsection", CF_line | CF_root | CF_sectioning_heading, LINE_line, 1, +"subsubheading", CF_line | CF_sectioning_heading | CF_close_paragraph, LINE_line, 1, +"subsubsection", CF_line | CF_root | CF_sectioning_heading, LINE_line, 1, +"subtitle", CF_line | CF_global | CF_contain_simple_text, LINE_line, 1, +"summarycontents", CF_line | CF_close_paragraph | CF_global, LINE_skipline, 1, +"sup", CF_brace, BRACE_style_other, 1, +"syncodeindex", CF_line | CF_contain_plain_text, LINE_specific, 2, +"synindex", CF_line | CF_contain_plain_text, LINE_specific, 2, +"t", CF_brace, BRACE_style_code, 1, +"tab", CF_nobrace | CF_close_paragraph, NOBRACE_skipspace, 1, +"table", CF_block | CF_close_paragraph | CF_blockitem | CF_contain_simple_text, BLOCK_item_line, 1, +"tex", CF_block, BLOCK_format_raw, 0, +"textdegree", CF_brace, BRACE_noarg, 0, +"th", CF_brace | CF_letter_no_arg, BRACE_noarg, 0, +"thischapter", CF_nobrace | CF_in_heading_spec, NOBRACE_other, 1, +"thischaptername", CF_nobrace | CF_in_heading_spec, NOBRACE_other, 1, +"thischapternum", CF_nobrace | CF_in_heading_spec, NOBRACE_other, 1, +"thisfile", CF_nobrace | CF_in_heading_spec, NOBRACE_other, 1, +"thispage", CF_nobrace | CF_in_heading_spec, NOBRACE_other, 1, +"thissection", CF_nobrace | CF_in_heading_spec, NOBRACE_other, 1, +"thissectionname", CF_nobrace | CF_in_heading_spec, NOBRACE_other, 1, +"thissectionnum", CF_nobrace | CF_in_heading_spec, NOBRACE_other, 1, +"thistitle", CF_nobrace | CF_in_heading_spec, NOBRACE_other, 1, +"tie", CF_brace, BRACE_noarg, 0, +"tieaccent", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"title", CF_line | CF_global_unique | CF_contain_simple_text, LINE_line, 1, +"titlefont", CF_brace | CF_close_paragraph | CF_global | CF_contain_simple_text, BRACE_other, 1, +"titlepage", CF_block | CF_close_paragraph | CF_global_unique, BLOCK_region, 0, +"today", CF_brace, BRACE_noarg, 0, +"top", CF_line | CF_root | CF_sectioning_heading | CF_global_unique, LINE_line, 1, +"txiinternalvalue", CF_internal | CF_brace, INTERNAL_brace, 1, +"u", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"ubaraccent", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"udotaccent", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"unmacro", CF_line, LINE_special, 1, +"unnumbered", CF_line | CF_root | CF_sectioning_heading, LINE_line, 1, +"unnumberedsec", CF_line | CF_root | CF_sectioning_heading, LINE_line, 1, +"unnumberedsubsec", CF_line | CF_root | CF_sectioning_heading, LINE_line, 1, +"unnumberedsubsubsec", CF_line | CF_root | CF_sectioning_heading, LINE_line, 1, +"uref", CF_brace | CF_contain_simple_text, BRACE_arguments, 3, +"urefbreakstyle", CF_line | CF_global | CF_contain_plain_text, LINE_specific, 1, +"url", CF_brace | CF_contain_simple_text, BRACE_arguments, 3, +"v", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, +"value", CF_brace, BRACE_special, 1, +"var", CF_brace, BRACE_style_other, 1, +"verb", CF_brace, BRACE_special, 1, +"verbatim", CF_block | CF_close_paragraph, BLOCK_raw, 0, +"verbatiminclude", CF_line | CF_close_paragraph | CF_contain_plain_text, LINE_text, 1, +"vskip", CF_line, LINE_lineraw, 1, +"vtable", CF_block | CF_close_paragraph | CF_blockitem | CF_contain_simple_text, BLOCK_item_line, 1, +"w", CF_brace | CF_contain_simple_text, BRACE_special, 1, +"xml", CF_block, BLOCK_format_raw, 0, +"xref", CF_brace | CF_ref | CF_contain_simple_text, BRACE_arguments, 5, +"xrefautomaticsectiontitle", CF_line | CF_global | CF_contain_plain_text, LINE_specific, 1, +"{", CF_nobrace, NOBRACE_symbol, 0, +"|", CF_nobrace | CF_in_heading_spec, NOBRACE_symbol, 1, +"}", CF_nobrace, NOBRACE_symbol, 0, +"~", CF_brace | CF_accent | CF_contain_plain_text, BRACE_accent, 1, }; diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_data.txt b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_data.txt index e5d5643a46..db884cb5fb 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_data.txt +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_data.txt @@ -15,41 +15,76 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -# Information from tp/Texinfo/Common.pm +# this information is used to setup both the XS Parser commands +# builtin_command_data and the perl Parser commands classification +# hashes. + +# Some documentation of the flags (second column) is in commands.h. + +############################################################## +# Internal commands +# invalid if not accept_internalvalue set in configuration +txiinternalvalue internal,brace INTERNAL_brace + +# nobrace: +# commands never taking braces nor arguments on the line +# +# symbol: non-alphabetical one letter commands without braces. +# skipspace: following spaces are skipped. +# other: other. -# Not in Common.pm -value brace ############################################################## # no brace commands - single letter commands -* nobrace +* nobrace NOBRACE_symbol # space -\x20 nobrace -\t nobrace -\n nobrace -- nobrace -| nobrace -/ nobrace -: nobrace -! nobrace -? nobrace -. nobrace -@ nobrace -& nobrace -} nobrace -{ nobrace -\\ nobrace +\x20 nobrace NOBRACE_symbol +\t nobrace NOBRACE_symbol +\n nobrace NOBRACE_symbol +- nobrace NOBRACE_symbol +| nobrace,in_heading_spec NOBRACE_symbol +/ nobrace NOBRACE_symbol +: nobrace NOBRACE_symbol +! nobrace NOBRACE_symbol +? nobrace NOBRACE_symbol +. nobrace NOBRACE_symbol +@ nobrace NOBRACE_symbol +& nobrace NOBRACE_symbol +} nobrace NOBRACE_symbol +{ nobrace NOBRACE_symbol +\\ nobrace NOBRACE_symbol ########################################################## # # line commands # ########################################################## -node line LINE_line + +# commands taking a line as argument or no argument. +# index commands are added dynamically. +# +# The values signification is: +# special: no value and macro expansion, all the line is used, and +# analysed during parsing (_parse_special_misc_command) +# lineraw: no value and macro expansion, the line is kept as-is, not +# analysed +# skipline: no argument, everything else on the line is skipped +# text: the line is parsed as texinfo, and the argument is converted +# to simple text with convert_to_text allowing only a few @-commands +# line: the line is parsed as texinfo +# specific: the line is parsed as texinfo and the result should be plain +# text maybe followed by a comment; the result is analysed +# during parsing (parse_line_command_args). +# +# Beware that @item may be a 'line' command or a 'nobrace' command +# depending on the context. + +# line commands number of arguments is only set for LINE_specific commands +# and is not used anywhere in the code, it is here as documentation only bye line LINE_skipline -end line LINE_text -# set, clear +end line,contain_plain_text LINE_text +# set, clear, special argument set line LINE_special clear line LINE_special unmacro line LINE_special @@ -57,119 +92,148 @@ unmacro line LINE_special c line LINE_lineraw comment line LINE_lineraw # special -definfoenclose line,deprecated 3 -alias line 2 +definfoenclose line,contain_plain_text,deprecated LINE_specific 3 +alias line,contain_plain_text LINE_specific 2 # number of arguments is not known in advance. -columnfractions line 1 -# file names -setfilename line,global_unique LINE_text -verbatiminclude line LINE_text -include line LINE_text - -raisesections line LINE_skipline -lowersections line LINE_skipline -contents line,global LINE_skipline -shortcontents line,global LINE_skipline -summarycontents line,global LINE_skipline -insertcopying line,global LINE_skipline -clickstyle line,global LINE_special +columnfractions line,contain_plain_text LINE_specific +# file names. +setfilename line,close_paragraph,global_unique,contain_plain_text LINE_text +verbatiminclude line,close_paragraph,contain_plain_text LINE_text +include line,contain_plain_text LINE_text + +raisesections line LINE_skipline +lowersections line LINE_skipline +contents line,close_paragraph,global LINE_skipline +shortcontents line,close_paragraph,global LINE_skipline +summarycontents line,close_paragraph,global LINE_skipline +insertcopying line,close_paragraph,global LINE_skipline +# arg should be an @-command +clickstyle line,global LINE_special # more relevant in preamble -documentencoding line,global LINE_text -novalidate line,global_unique LINE_skipline -dircategory line LINE_line -# with direntry is significant -pagesizes line,global_unique LINE_line -# or one? 200mm,150mm 11.5in +documentencoding line,global,contain_plain_text LINE_text +novalidate line,global_unique LINE_skipline +# Position with regard with direntry is significant +dircategory line,close_paragraph,contain_simple_text LINE_line +# arg like 200mm,150mm or 11.5in +pagesizes line,global_unique,contain_plain_text LINE_line finalout line LINE_skipline -paragraphindent line,global 1 +# arg none asis # or a number and forbids anything else on the line -firstparagraphindent line,global 1 -frenchspacing line,global 1 -codequoteundirected line,global 1 -codequotebacktick line,global 1 -xrefautomaticsectiontitle line,global 1 -deftypefnnewline line,global 1 -fonttextsize line,global_unique 1 -allowcodebreaks line,global 1 -exampleindent line,global 1 -footnotestyle line,global_unique 1 -urefbreakstyle line,global 1 -afourpaper line LINE_skipline -afivepaper line LINE_skipline -afourlatex line LINE_skipline -afourwide line LINE_skipline -bsixpaper line LINE_skipline -headings line,global 1 -setchapternewpage line,global_unique 1 - -# only relevant in TeX, and special -everyheading line,global_unique LINE_lineraw -everyfooting line,global_unique LINE_lineraw -evenheading line,global_unique LINE_lineraw -evenfooting line,global_unique LINE_lineraw -oddheading line,global_unique LINE_lineraw -oddfooting line,global_unique LINE_lineraw - -smallbook line LINE_skipline -syncodeindex line 2 -synindex line 2 -defindex line 1 -defcodeindex line 1 -documentlanguage line,global LINE_text -kbdinputstyle line,global 1 -everyheadingmarks line,global_unique 1 -everyfootingmarks line,global_unique 1 -evenheadingmarks line,global_unique 1 -oddheadingmarks line,global_unique 1 -evenfootingmarks line,global_unique 1 -oddfootingmarks line,global_unique 1 +paragraphindent line,global,contain_plain_text LINE_specific 1 +# arg none insert +firstparagraphindent line,global,contain_plain_text LINE_specific 1 +# arg on off +frenchspacing line,global,contain_plain_text LINE_specific 1 +# arg on off +codequoteundirected line,global,contain_plain_text LINE_specific 1 +# arg on off +codequotebacktick line,global,contain_plain_text LINE_specific 1 +# arg on off +xrefautomaticsectiontitle line,global,contain_plain_text LINE_specific 1 +# arg on off +deftypefnnewline line,global,contain_plain_text LINE_specific 1 +# arg 10 11 +fonttextsize line,global_unique,contain_plain_text LINE_specific 1 +# arg false or true +allowcodebreaks line,global,contain_plain_text LINE_specific 1 +# arg asis or a number +exampleindent line,global,contain_plain_text LINE_specific 1 +# args end and separate, nothing else on the line +footnotestyle line,global_unique,contain_plain_text LINE_specific 1 +# arg after|before|none +urefbreakstyle line,global,contain_plain_text LINE_specific 1 +smallbook line,global_unique LINE_skipline +afourpaper line,global_unique LINE_skipline +afivepaper line,global_unique LINE_skipline +afourlatex line,global_unique LINE_skipline +afourwide line,global_unique LINE_skipline +bsixpaper line,global_unique LINE_skipline +# arg off on single double singleafter doubleafter +# interacts with setchapternewpage +headings line,global,contain_plain_text LINE_specific 1 +# arg off on odd +setchapternewpage line,global_unique,contain_plain_text LINE_specific 1 +# arg on off +microtype line,global,contain_plain_text LINE_specific 1 + +everyheading line,global,heading_spec,contain_simple_text LINE_line +everyfooting line,global,heading_spec,contain_simple_text LINE_line +evenheading line,global,heading_spec,contain_simple_text LINE_line +evenfooting line,global,heading_spec,contain_simple_text LINE_line +oddheading line,global,heading_spec,contain_simple_text LINE_line +oddfooting line,global,heading_spec,contain_simple_text LINE_line + +# args are index identifiers +syncodeindex line,contain_plain_text LINE_specific 2 +synindex line,contain_plain_text LINE_specific 2 +# one identifier arg +defindex line,contain_plain_text LINE_specific 1 +# one identifier arg +defcodeindex line,contain_plain_text LINE_specific 1 +# language code arg +documentlanguage line,global,contain_plain_text,contain_plain_text LINE_text +# arg code example distinct +kbdinputstyle line,global,contain_plain_text LINE_specific 1 +# arg top bottom +everyheadingmarks line,global_unique,contain_plain_text LINE_specific 1 +everyfootingmarks line,global_unique,contain_plain_text LINE_specific 1 +evenheadingmarks line,global_unique,contain_plain_text LINE_specific 1 +oddheadingmarks line,global_unique,contain_plain_text LINE_specific 1 +evenfootingmarks line,global_unique,contain_plain_text LINE_specific 1 +oddfootingmarks line,global_unique,contain_plain_text LINE_specific 1 # formatting -center line LINE_line -printindex line,global 1 -listoffloats line,global LINE_line +center line,close_paragraph LINE_line +printindex line,close_paragraph,global,contain_plain_text LINE_specific 1 +listoffloats line,close_paragraph,global,contain_simple_text LINE_line # especially in titlepage # shorttitle -shorttitlepage line,global_unique LINE_line -settitle line,global_unique LINE_line -author line,global LINE_line -subtitle line,global LINE_line -title line,global_unique LINE_line -sp line 1 -page line LINE_skipline -need line 1 +shorttitlepage line,global_unique,contain_simple_text LINE_line +settitle line,global_unique,contain_simple_text LINE_line +author line,global,contain_simple_text LINE_line +subtitle line,global,contain_simple_text LINE_line +title line,global_unique,contain_simple_text LINE_line +# numerical arg +sp line,close_paragraph,contain_plain_text LINE_specific 1 +page line,close_paragraph LINE_skipline +# one numerical/real arg +need line,close_paragraph,contain_plain_text LINE_specific 1 # not valid for info (should be in @iftex) vskip line LINE_lineraw -exdent line LINE_line +exdent line,close_paragraph LINE_line -item_LINE line LINE_line -itemx line LINE_line +# or nobrace skipspace, depending on the context +item_LINE line,close_paragraph,contain_simple_text LINE_line +itemx line,close_paragraph,contain_simple_text LINE_line -subentry line LINE_line +subentry line,contain_simple_text LINE_line ########################################################## # -# miscellaneous commands +# no brace commands - miscellaneous commands # ########################################################## # formatting -noindent other OTHER_skipspace -indent other OTHER_skipspace -headitem other OTHER_skipspace -item other OTHER_skipspace -tab other OTHER_skipspace +noindent nobrace NOBRACE_skipspace +indent nobrace NOBRACE_skipspace +headitem nobrace,close_paragraph NOBRACE_skipspace +item nobrace,close_paragraph NOBRACE_skipspace +tab nobrace,close_paragraph NOBRACE_skipspace # only valid in heading or footing -thischapter other,in_heading OTHER_noarg -thischaptername other,in_heading OTHER_noarg -thischapternum other,in_heading OTHER_noarg -thisfile other,in_heading OTHER_noarg -thispage other,in_heading OTHER_noarg -thistitle other,in_heading OTHER_noarg +thischapter nobrace,in_heading_spec NOBRACE_other +thischaptername nobrace,in_heading_spec NOBRACE_other +thischapternum nobrace,in_heading_spec NOBRACE_other +thissection nobrace,in_heading_spec NOBRACE_other +thissectionname nobrace,in_heading_spec NOBRACE_other +thissectionnum nobrace,in_heading_spec NOBRACE_other +thisfile nobrace,in_heading_spec NOBRACE_other +thispage nobrace,in_heading_spec NOBRACE_other +thistitle nobrace,in_heading_spec NOBRACE_other # obsolete @-commands. -refill other,deprecated OTHER_noarg +refill nobrace,deprecated NOBRACE_other @@ -180,269 +244,285 @@ refill other,deprecated OTHER_noarg ########################################################## # letter_no_arg_commands -aa brace 0 -AA brace 0 -ae brace 0 -oe brace 0 -AE brace 0 -OE brace 0 -o brace 0 -O brace 0 -ss brace 0 -l brace 0 -L brace 0 -DH brace 0 -dh brace 0 -TH brace 0 -th brace 0 +aa brace,letter_no_arg BRACE_noarg +AA brace,letter_no_arg BRACE_noarg +ae brace,letter_no_arg BRACE_noarg +oe brace,letter_no_arg BRACE_noarg +AE brace,letter_no_arg BRACE_noarg +OE brace,letter_no_arg BRACE_noarg +o brace,letter_no_arg BRACE_noarg +O brace,letter_no_arg BRACE_noarg +ss brace,letter_no_arg BRACE_noarg +l brace,letter_no_arg BRACE_noarg +L brace,letter_no_arg BRACE_noarg +DH brace,letter_no_arg BRACE_noarg +dh brace,letter_no_arg BRACE_noarg +TH brace,letter_no_arg BRACE_noarg +th brace,letter_no_arg BRACE_noarg # no arg commands -TeX brace 0 -LaTeX brace 0 -bullet brace 0 -copyright brace 0 -registeredsymbol brace 0 -dots brace 0 -enddots brace 0 -equiv brace 0 -error brace 0 -expansion brace 0 -arrow brace 0 -minus brace 0 -point brace 0 -print brace 0 -result brace 0 -today brace 0 -exclamdown brace 0 -questiondown brace 0 -pounds brace 0 -ordf brace 0 -ordm brace 0 -atchar brace 0 -ampchar brace 0 -lbracechar brace 0 -rbracechar brace 0 -backslashchar brace 0 -hashchar brace 0 -comma brace 0 -euro brace 0 -geq brace 0 -leq brace 0 -tie brace 0 -textdegree brace 0 -click brace 0 -quotedblleft brace 0 -quotedblright brace 0 -quoteleft brace 0 -quoteright brace 0 -quotedblbase brace 0 -quotesinglbase brace 0 -guillemetleft brace 0 -guillemetright brace 0 -guillemotleft brace 0 -guillemotright brace 0 -guilsinglleft brace 0 -guilsinglright brace 0 +TeX brace BRACE_noarg +LaTeX brace BRACE_noarg +bullet brace BRACE_noarg +copyright brace BRACE_noarg +registeredsymbol brace BRACE_noarg +dots brace BRACE_noarg +enddots brace BRACE_noarg +equiv brace BRACE_noarg +error brace BRACE_noarg +expansion brace BRACE_noarg +arrow brace BRACE_noarg +minus brace BRACE_noarg +point brace BRACE_noarg +print brace BRACE_noarg +result brace BRACE_noarg +today brace BRACE_noarg +exclamdown brace BRACE_noarg +questiondown brace BRACE_noarg +pounds brace BRACE_noarg +ordf brace BRACE_noarg +ordm brace BRACE_noarg +atchar brace BRACE_noarg +ampchar brace BRACE_noarg +lbracechar brace BRACE_noarg +rbracechar brace BRACE_noarg +backslashchar brace BRACE_noarg +hashchar brace BRACE_noarg +comma brace BRACE_noarg +euro brace BRACE_noarg +geq brace BRACE_noarg +leq brace BRACE_noarg +tie brace BRACE_noarg +textdegree brace BRACE_noarg +click brace BRACE_noarg +quotedblleft brace BRACE_noarg +quotedblright brace BRACE_noarg +quoteleft brace BRACE_noarg +quoteright brace BRACE_noarg +quotedblbase brace BRACE_noarg +quotesinglbase brace BRACE_noarg +guillemetleft brace BRACE_noarg +guillemetright brace BRACE_noarg +guillemotleft brace BRACE_noarg +guillemotright brace BRACE_noarg +guilsinglleft brace BRACE_noarg +guilsinglright brace BRACE_noarg # accent commands - can be called with or without braces -\" brace,accent BRACE_accent -~ brace,accent BRACE_accent -^ brace,accent BRACE_accent -` brace,accent BRACE_accent -' brace,accent BRACE_accent -, brace,accent BRACE_accent -= brace,accent BRACE_accent -ringaccent brace,accent BRACE_accent -H brace,accent BRACE_accent -dotaccent brace,accent BRACE_accent -u brace,accent BRACE_accent -ubaraccent brace,accent BRACE_accent -udotaccent brace,accent BRACE_accent -v brace,accent BRACE_accent -ogonek brace,accent BRACE_accent -tieaccent brace,accent BRACE_accent -dotless brace,accent BRACE_accent +\" brace,accent,contain_plain_text BRACE_accent +~ brace,accent,contain_plain_text BRACE_accent +^ brace,accent,contain_plain_text BRACE_accent +` brace,accent,contain_plain_text BRACE_accent +' brace,accent,contain_plain_text BRACE_accent +, brace,accent,contain_plain_text BRACE_accent += brace,accent,contain_plain_text BRACE_accent +ringaccent brace,accent,contain_plain_text BRACE_accent +H brace,accent,contain_plain_text BRACE_accent +dotaccent brace,accent,contain_plain_text BRACE_accent +u brace,accent,contain_plain_text BRACE_accent +ubaraccent brace,accent,contain_plain_text BRACE_accent +udotaccent brace,accent,contain_plain_text BRACE_accent +v brace,accent,contain_plain_text BRACE_accent +ogonek brace,accent,contain_plain_text BRACE_accent +tieaccent brace,accent,contain_plain_text BRACE_accent +dotless brace,accent,contain_plain_text BRACE_accent # Style commands -asis brace BRACE_style -cite brace BRACE_style -clicksequence brace BRACE_style -dfn brace BRACE_style -emph brace BRACE_style -sc brace BRACE_style -t brace BRACE_style -var brace BRACE_style -headitemfont brace BRACE_style -code brace,code_style BRACE_style -command brace,code_style BRACE_style -env brace,code_style BRACE_style -file brace,code_style BRACE_style -kbd brace,code_style BRACE_style -option brace,code_style BRACE_style -samp brace,code_style BRACE_style -strong brace BRACE_style -sub brace BRACE_style -sup brace BRACE_style - -# Regular font style commands -r brace BRACE_style -i brace BRACE_style -b brace BRACE_style -sansserif brace BRACE_style -slanted brace BRACE_style - -U brace 1 -dmn brace 1 -titlefont brace,global 1 - -w brace BRACE_other -key brace BRACE_other - -hyphenation brace,global BRACE_other -anchor brace 1 -errormsg brace 1 -sortas brace 1 -seeentry brace 1 -seealso brace 1 - -# more code style commands -indicateurl brace,code_style 1 -verb brace,code_style BRACE_other -t brace,code_style BRACE_other +asis brace BRACE_style_other +i brace BRACE_style_other +b brace BRACE_style_other +sansserif brace BRACE_style_other +slanted brace BRACE_style_other +cite brace BRACE_style_other +clicksequence brace BRACE_style_other +dfn brace BRACE_style_other +emph brace BRACE_style_other +sc brace BRACE_style_other +var brace BRACE_style_other +headitemfont brace BRACE_style_other +strong brace BRACE_style_other +sub brace BRACE_style_other +sup brace BRACE_style_other + +# code style commands +code brace BRACE_style_code +command brace BRACE_style_code +env brace BRACE_style_code +file brace BRACE_style_code +indicateurl brace BRACE_style_code +kbd brace BRACE_style_code +key brace,contain_plain_text BRACE_style_code +option brace BRACE_style_code +samp brace BRACE_style_code +t brace BRACE_style_code + +# No code style commands +r brace BRACE_style_no_code + +# in this category, the leading and trailing spaces are put in specific +# text with type, but commas do not delimitate arguments. +# As other arguments brace_commands, they can only contain simple text, +# ie not ref, footnote, titlefont, anchor, verb. +# Parsers have specific checks for U content. +U brace BRACE_arguments 1 +hyphenation brace,global,contain_plain_text BRACE_arguments 1 +anchor brace,contain_simple_text BRACE_arguments 1 +errormsg brace,contain_simple_text BRACE_arguments 1 +sortas brace,contain_plain_text BRACE_arguments 1 +seeentry brace,contain_simple_text BRACE_arguments 1 +seealso brace,contain_simple_text BRACE_arguments 1 + +# Leading and trailing spaces kept in main text. +# verb is treated especially, it should not matter much in which category it is. +# value also is treated especially. +value brace BRACE_special +verb brace BRACE_special +w brace,contain_simple_text BRACE_special + +# other brace commands, leading and trailing spaces kept in main text +dmn brace,contain_plain_text BRACE_other 1 +titlefont brace,close_paragraph,global,contain_simple_text BRACE_other 1 # context brace commands - commands that enclose full texts +# not in the main document context. They can contain multiple paragraphs. footnote brace,global BRACE_context -caption brace BRACE_context -shortcaption brace BRACE_context -math brace BRACE_context +caption brace,close_paragraph BRACE_context +shortcaption brace,close_paragraph,contain_simple_text BRACE_context +# Commands that enclose math content, and, because of that, are not in the +# main document context. +math brace,math,contain_simple_text BRACE_context # explained commands -abbr brace 2 -acronym brace 2 +abbr brace,contain_simple_text BRACE_arguments 2 +acronym brace,contain_simple_text BRACE_arguments 2 +# leading space is ignored in inline brace commands, not trailing space # inline format command -inlineraw brace,inline 2 -inlinefmt brace,inline 2 -inlinefmtifelse brace,inline 3 +inlineraw brace BRACE_inline 2 +inlinefmt brace BRACE_inline 2 +inlinefmtifelse brace BRACE_inline 3 # inline conditional commands -inlineifclear brace,inline 2 -inlineifset brace,inline 2 +inlineifclear brace BRACE_inline 2 +inlineifset brace BRACE_inline 2 -email brace 2 +email brace,contain_simple_text BRACE_arguments 2 -uref brace 3 -url brace 3 -inforef brace,ref,deprecated 3 +uref brace,contain_simple_text BRACE_arguments 3 +url brace,contain_simple_text BRACE_arguments 3 +inforef brace,ref,contain_simple_text,deprecated BRACE_arguments 3 -xref brace,ref 5 -ref brace,ref 5 -pxref brace,ref 5 -image brace 5 +xref brace,ref,contain_simple_text BRACE_arguments 5 +ref brace,ref,contain_simple_text BRACE_arguments 5 +pxref brace,ref,contain_simple_text BRACE_arguments 5 +image brace,contain_simple_text BRACE_arguments 5 ########################################################## +# commands delimiting blocks, with an @end. # def* commands -deffn block,def -defvr block,def -deftypefn block,def -deftypeop block,def -deftypevr block,def -defcv block,def -deftypecv block,def -defop block,def -deftp block,def +deffn block,def,close_paragraph BLOCK_def +defvr block,def,close_paragraph BLOCK_def +deftypefn block,def,close_paragraph BLOCK_def +deftypeop block,def,close_paragraph BLOCK_def +deftypevr block,def,close_paragraph BLOCK_def +defcv block,def,close_paragraph BLOCK_def +deftypecv block,def,close_paragraph BLOCK_def +defop block,def,close_paragraph BLOCK_def +deftp block,def,close_paragraph BLOCK_def # shortcuts -defun block,def,def_alias -defmac block,def,def_alias -defspec block,def,def_alias -defvar block,def,def_alias -defopt block,def,def_alias -deftypefun block,def,def_alias -deftypevar block,def,def_alias -defivar block,def,def_alias -deftypeivar block,def,def_alias -defmethod block,def,def_alias -deftypemethod block,def,def_alias +defun block,def,def_alias,close_paragraph BLOCK_def +defmac block,def,def_alias,close_paragraph BLOCK_def +defspec block,def,def_alias,close_paragraph BLOCK_def +defvar block,def,def_alias,close_paragraph BLOCK_def +defopt block,def,def_alias,close_paragraph BLOCK_def +deftypefun block,def,def_alias,close_paragraph BLOCK_def +deftypevar block,def,def_alias,close_paragraph BLOCK_def +defivar block,def,def_alias,close_paragraph BLOCK_def +deftypeivar block,def,def_alias,close_paragraph BLOCK_def +defmethod block,def,def_alias,close_paragraph BLOCK_def +deftypemethod block,def,def_alias,close_paragraph BLOCK_def # def*x -deffnx line,def LINE_line -defvrx line,def LINE_line -deftypefnx line,def LINE_line -deftypeopx line,def LINE_line -deftypevrx line,def LINE_line -defcvx line,def LINE_line -deftypecvx line,def LINE_line -defopx line,def LINE_line -deftpx line,def LINE_line +deffnx line,def,close_paragraph LINE_line +defvrx line,def,close_paragraph LINE_line +deftypefnx line,def,close_paragraph LINE_line +deftypeopx line,def,close_paragraph LINE_line +deftypevrx line,def,close_paragraph LINE_line +defcvx line,def,close_paragraph LINE_line +deftypecvx line,def,close_paragraph LINE_line +defopx line,def,close_paragraph LINE_line +deftpx line,def,close_paragraph LINE_line # shortcuts -defunx line,def,def_alias LINE_line -defmacx line,def,def_alias LINE_line -defspecx line,def,def_alias LINE_line -defvarx line,def,def_alias LINE_line -defoptx line,def,def_alias LINE_line -deftypefunx line,def,def_alias LINE_line -deftypevarx line,def,def_alias LINE_line -defivarx line,def,def_alias LINE_line -deftypeivarx line,def,def_alias LINE_line -defmethodx line,def,def_alias LINE_line -deftypemethodx line,def,def_alias LINE_line - -multitable block,blockitem BLOCK_multitable - -# menu commands -menu block,menu -detailmenu block,menu,global -direntry block,menu +defunx line,def,def_alias,close_paragraph LINE_line +defmacx line,def,def_alias,close_paragraph LINE_line +defspecx line,def,def_alias,close_paragraph LINE_line +defvarx line,def,def_alias,close_paragraph LINE_line +defoptx line,def,def_alias,close_paragraph LINE_line +deftypefunx line,def,def_alias,close_paragraph LINE_line +deftypevarx line,def,def_alias,close_paragraph LINE_line +defivarx line,def,def_alias,close_paragraph LINE_line +deftypeivarx line,def,def_alias,close_paragraph LINE_line +defmethodx line,def,def_alias,close_paragraph LINE_line +deftypemethodx line,def,def_alias,close_paragraph LINE_line + +multitable block,close_paragraph,blockitem,contain_simple_text BLOCK_multitable + +# menu commands in which menu entry and menu comments appear +menu block,close_paragraph BLOCK_menu +detailmenu block,close_paragraph,global BLOCK_menu +direntry block,close_paragraph BLOCK_menu # align commands -raggedright block -flushleft block -flushright block +raggedright block,close_paragraph +flushleft block,close_paragraph +flushright block,close_paragraph +indentedblock block,close_paragraph +smallindentedblock block,close_paragraph -cartouche block -group block -indentedblock block -smallindentedblock block +cartouche block,close_paragraph +group block,close_paragraph # region commands -titlepage block,global_unique BLOCK_region -copying block,global_unique BLOCK_region -documentdescription block,global_unique BLOCK_region +titlepage block,close_paragraph,global_unique BLOCK_region +copying block,close_paragraph,global_unique BLOCK_region +documentdescription block,close_paragraph,global_unique BLOCK_region # preformatted commands -example block,preformatted,preformatted_code BLOCK_variadic -smallexample block,preformatted,preformatted_code -lisp block,preformatted,preformatted_code -smalllisp block,preformatted,preformatted_code -display block,preformatted -smalldisplay block,preformatted -format block,preformatted -smallformat block,preformatted +example block,close_paragraph,preformatted,preformatted_code,variadic,contain_simple_text BLOCK_preformatted +smallexample block,close_paragraph,preformatted,preformatted_code BLOCK_preformatted +lisp block,close_paragraph,preformatted,preformatted_code BLOCK_preformatted +smalllisp block,close_paragraph,preformatted,preformatted_code BLOCK_preformatted +display block,close_paragraph,preformatted BLOCK_preformatted +smalldisplay block,close_paragraph,preformatted BLOCK_preformatted +format block,close_paragraph,preformatted BLOCK_preformatted +smallformat block,close_paragraph,preformatted BLOCK_preformatted # format raw commands -html block,format_raw -tex block,format_raw -xml block,format_raw -docbook block,format_raw +html block BLOCK_format_raw +tex block BLOCK_format_raw +xml block BLOCK_format_raw +docbook block BLOCK_format_raw +latex block BLOCK_format_raw # raw commands -verbatim block BLOCK_raw -ignore block BLOCK_raw -macro block BLOCK_raw -rmacro block BLOCK_raw - -table block,blockitem 1 -ftable block,blockitem 1 -vtable block,blockitem 1 -itemize block,blockitem 1 -enumerate block,blockitem 1 -quotation block 1 -smallquotation block 1 - -float block 2 -displaymath block 0 +verbatim block,close_paragraph BLOCK_raw +ignore block BLOCK_raw +macro block BLOCK_raw +rmacro block BLOCK_raw + +table block,close_paragraph,blockitem,contain_simple_text BLOCK_item_line 1 +ftable block,close_paragraph,blockitem,contain_simple_text BLOCK_item_line 1 +vtable block,close_paragraph,blockitem,contain_simple_text BLOCK_item_line 1 +itemize block,close_paragraph,blockitem,contain_simple_text BLOCK_item_container 1 +enumerate block,close_paragraph,blockitem,contain_simple_text BLOCK_item_container 1 +quotation block,close_paragraph,contain_simple_text BLOCK_quotation 1 +smallquotation block,close_paragraph,contain_simple_text BLOCK_quotation 1 + +float block,close_paragraph,contain_simple_text BLOCK_float 2 + +displaymath block,close_paragraph,math BLOCK_math ################################################################## # Conditional commands @@ -458,6 +538,8 @@ ifinfo block BLOCK_conditional ifnotinfo block BLOCK_conditional ifplaintext block BLOCK_conditional ifnotplaintext block BLOCK_conditional +iflatex block BLOCK_conditional +ifnotlatex block BLOCK_conditional ifset block BLOCK_conditional ifclear block BLOCK_conditional ifcommanddefined block BLOCK_conditional @@ -465,27 +547,27 @@ ifcommandnotdefined block BLOCK_conditional ########################################################## # Root commands -node root,line LINE_line -top root,line,sectioning,global_unique LINE_line -chapter root,line,sectioning LINE_line -unnumbered root,line,sectioning LINE_line -chapheading line,sectioning LINE_line -appendix root,line,sectioning LINE_line -section root,line,sectioning LINE_line -unnumberedsec root,line,sectioning LINE_line -heading line,sectioning LINE_line -appendixsec root,line,sectioning LINE_line -subsection root,line,sectioning LINE_line -unnumberedsubsec root,line,sectioning LINE_line -subheading line,sectioning LINE_line -appendixsubsec root,line,sectioning LINE_line -subsubsection root,line,sectioning LINE_line -unnumberedsubsubsec root,line,sectioning LINE_line -subsubheading line,sectioning LINE_line -appendixsubsubsec root,line,sectioning LINE_line - -part root,line,sectioning,global LINE_line -appendixsection root,line,sectioning LINE_line -majorheading line,sectioning LINE_line -centerchap root,line,sectioning,deprecated LINE_line +node line,root,contain_simple_text LINE_line 4 +top line,root,sectioning_heading,global_unique LINE_line +chapter line,root,sectioning_heading LINE_line +unnumbered line,root,sectioning_heading LINE_line +chapheading line,sectioning_heading,close_paragraph LINE_line +appendix line,root,sectioning_heading LINE_line +section line,root,sectioning_heading LINE_line +unnumberedsec line,root,sectioning_heading LINE_line +heading line,sectioning_heading,close_paragraph LINE_line +appendixsec line,root,sectioning_heading LINE_line +subsection line,root,sectioning_heading LINE_line +unnumberedsubsec line,root,sectioning_heading LINE_line +subheading line,sectioning_heading,close_paragraph LINE_line +appendixsubsec line,root,sectioning_heading LINE_line +subsubsection line,root,sectioning_heading LINE_line +unnumberedsubsubsec line,root,sectioning_heading LINE_line +subsubheading line,sectioning_heading,close_paragraph LINE_line +appendixsubsubsec line,root,sectioning_heading LINE_line + +part line,root,sectioning_heading,global LINE_line +appendixsection line,root,sectioning_heading LINE_line +majorheading line,sectioning_heading,close_paragraph LINE_line +centerchap line,root,sectioning_heading,deprecated LINE_line diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_ids.h b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_ids.h index 1201e40484..a2c8542ad2 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_ids.h +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/command_ids.h @@ -226,9 +226,11 @@ CM_ifcommandnotdefined, CM_ifdocbook, CM_ifhtml, CM_ifinfo, +CM_iflatex, CM_ifnotdocbook, CM_ifnothtml, CM_ifnotinfo, +CM_ifnotlatex, CM_ifnotplaintext, CM_ifnottex, CM_ifnotxml, @@ -257,6 +259,7 @@ CM_kbd, CM_kbdinputstyle, CM_key, CM_l, +CM_latex, CM_lbracechar, CM_leq, CM_lisp, @@ -266,6 +269,7 @@ CM_macro, CM_majorheading, CM_math, CM_menu, +CM_microtype, CM_minus, CM_multitable, CM_need, @@ -356,6 +360,9 @@ CM_thischaptername, CM_thischapternum, CM_thisfile, CM_thispage, +CM_thissection, +CM_thissectionname, +CM_thissectionnum, CM_thistitle, CM_tie, CM_tieaccent, @@ -364,6 +371,7 @@ CM_titlefont, CM_titlepage, CM_today, CM_top, +CM_txiinternalvalue, CM_u, CM_ubaraccent, CM_udotaccent, diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/commands.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/commands.c index e0caffd149..943afa42fa 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/commands.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/commands.c @@ -22,6 +22,12 @@ #include "commands.h" #include "errors.h" +/* FIXME pass global_accept_internalvalue to lookup_command instead of + * #include parser.h to get the global variable value? */ + +/* for global_accept_internalvalue */ +#include "parser.h" + #include "command_data.c" COMMAND *user_defined_command_data = 0; @@ -67,7 +73,18 @@ lookup_command (char *cmdname) compare_command_fn); if (c) - return c - &builtin_command_data[0]; + { + enum command_id cmd; + cmd = c - &builtin_command_data[0]; + + /* txiinternalvalue is invalid if the corresponding configuration + * is not set */ + if (cmd == CM_txiinternalvalue && !global_accept_internalvalue) { + return 0; + } + + return cmd; + } return 0; @@ -90,6 +107,7 @@ add_texinfo_command (char *name) user_defined_command_data[user_defined_number].cmdname = strdup (name); user_defined_command_data[user_defined_number].flags = 0; user_defined_command_data[user_defined_number].data = 0; + user_defined_command_data[user_defined_number].args_number = 0; return ((enum command_id) user_defined_number++) | USER_COMMAND_BIT; } @@ -112,68 +130,15 @@ wipe_user_commands (void) user_defined_number = 0; } -/* Commands that terminate a paragraph. */ -/* We may replace this function with a macro, or represent this infomation in - command_data. */ -int -close_paragraph_command (enum command_id cmd) -{ - if (cmd == CM_verbatim) - return 1; - - /* Block commands except 'raw' and 'conditional'. */ - - if (command_data(cmd).flags & CF_block) - { - if (command_data(cmd).data == BLOCK_conditional - || command_data(cmd).data == BLOCK_raw) - return 0; - if (command_data(cmd).flags & CF_format_raw) - return 0; - - return 1; - } - - if (cmd == CM_titlefont - || cmd == CM_insertcopying - || cmd == CM_sp - || cmd == CM_verbatiminclude - || cmd == CM_page - || cmd == CM_item - || cmd == CM_itemx - || cmd == CM_tab - || cmd == CM_headitem - || cmd == CM_printindex - || cmd == CM_listoffloats - || cmd == CM_center - || cmd == CM_dircategory - || cmd == CM_contents - || cmd == CM_shortcontents - || cmd == CM_summarycontents - || cmd == CM_caption - || cmd == CM_shortcaption - || cmd == CM_setfilename - || cmd == CM_exdent) - return 1; - - if ((command_data(cmd).flags & CF_sectioning) - && !(command_data(cmd).flags & CF_root)) - return 1; - - if ((command_data(cmd).flags & CF_def)) - return 1; - - return 0; -} - int close_preformatted_command (enum command_id cmd_id) { - return cmd_id != CM_sp && close_paragraph_command (cmd_id); + return cmd_id != CM_sp + && command_data(cmd_id).flags & CF_close_paragraph; } int item_line_command (enum command_id cmd_id) { - return cmd_id == CM_table || cmd_id == CM_ftable || cmd_id == CM_vtable; + return command_data(cmd_id).data == BLOCK_item_line; } diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/commands.h b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/commands.h index 92078a4c4d..60a119e284 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/commands.h +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/commands.h @@ -19,7 +19,8 @@ typedef struct command_struct { char *cmdname; unsigned long flags; /* Up to 32 flags */ - int data; /* Number of arguments for brace or line commands. */ + int data; /* type of command. */ + int args_number; /* Number of arguments for brace or line commands. */ } COMMAND; extern COMMAND builtin_command_data[]; @@ -38,7 +39,6 @@ enum command_id lookup_command (char *cmdname); #define command_flags(e) (!(e) ? 0 : (command_data((e)->cmd).flags)) #define command_name(cmd) (command_data(cmd).cmdname) -int close_paragraph_command (enum command_id cmd_id); int close_preformatted_command (enum command_id cmd_id); int item_line_command (enum command_id cmd_id); enum command_id add_texinfo_command (char *name); @@ -49,44 +49,56 @@ void wipe_user_commands (void); #define CF_line 0x0001 #define CF_deprecated 0x0002 +/* commands that should only appear at the root level and contain up to + the next root command. @node and sectioning commands. */ #define CF_root 0x0004 -#define CF_sectioning 0x0008 +/* sectioning and heading commands */ +#define CF_sectioning_heading 0x0008 #define CF_brace 0x0010 +/* CF_letter_no_arg is not used in XS parser, used in perl */ #define CF_letter_no_arg 0x0020 #define CF_accent 0x0040 -#define CF_style 0x0080 -/* CF_code_style is set for brace commands only. */ -#define CF_code_style 0x0100 +/* CF_math is not used in XS parser, used in perl */ +#define CF_math 0x0080 +/* commands with an unlimited number of arguments */ +#define CF_variadic 0x0100 #define CF_INFOENCLOSE 0x0200 -#define CF_in_heading 0x0400 +/* in_heading_spec only valid in heading or footing specifications */ +#define CF_in_heading_spec 0x0400 #define CF_ref 0x0800 #define CF_ALIAS 0x1000 #define CF_block 0x2000 -#define CF_raw 0x4000 -#define CF_format_raw 0x8000 -#define CF_global 0x00010000 +/* in_heading_spec commands are only valid in heading_spec */ +#define CF_heading_spec 0x4000 +/* CF_internal is not used in code, but it should be kept as internal + * commands marker */ +#define CF_internal 0x8000 +#define CF_global 0x00010000 #define CF_def 0x00020000 #define CF_def_alias 0x00040000 -#define CF_menu 0x00080000 -#define CF_align 0x00100000 -#define CF_other 0x00200000 +/* only accept plain text, ie only accent, symbol and glyph commands */ +#define CF_contain_plain_text 0x00080000 +/* CF_close_paragraph commands force closing an opened paragraph */ +#define CF_close_paragraph 0x00100000 +/* for commands containing simple text only, corresponding to paragraph + text without @ref, @footnote, @titlefont, @anchor nor @verb. */ +#define CF_contain_simple_text 0x00200000 #define CF_preformatted 0x00400000 #define CF_preformatted_code 0x00800000 +/* CF_item_container is not used */ #define CF_item_container 0x01000000 +/* CF_item_line is not used */ #define CF_item_line 0x02000000 #define CF_nobrace 0x04000000 +/* blockitem commands have a possible content before an item */ #define CF_blockitem 0x08000000 +/* CF_inline is not used */ #define CF_inline 0x10000000 #define CF_MACRO 0x20000000 #define CF_index_entry_command 0x40000000 #define CF_global_unique 0x80000000 -/* NOTE: We've run out of spaces for flags, but some of these may not - be used, or may not be necessary. - CF_code_style, CF_deprecated are hardly used. - - Candidates for flags: - CF_close_paragraph +/* NOTE: We often run out of spaces for flags Could combine CF_MACRO, CF_ALIAS, and CF_INFOENCLOSE into 2 bits. */ @@ -95,24 +107,48 @@ void wipe_user_commands (void); #define LINE_special -1 #define LINE_lineraw -2 #define LINE_skipline -3 +#define LINE_specific -4 #define LINE_text -6 #define LINE_line -7 -/* Types of other command (has CF_other flag). */ -#define OTHER_skipspace -1 -#define OTHER_noarg -2 +/* Types of command without brace nor argument on line (has CF_nobrace flag). */ +#define NOBRACE_symbol 0 +#define NOBRACE_skipspace -1 +#define NOBRACE_other -2 /* Types of block command (CF_block). */ #define BLOCK_conditional -1 #define BLOCK_raw -2 #define BLOCK_multitable -3 #define BLOCK_region -4 -#define BLOCK_variadic -5 +#define BLOCK_item_line -5 +/* not used in code but consistent with type in perl hash */ +#define BLOCK_item_container -6 +/* not used in code but consistent with type in perl hash */ +#define BLOCK_quotation -7 +#define BLOCK_float -8 +#define BLOCK_menu -9 +#define BLOCK_format_raw -10 +/* not used in code but consistent with type in perl hash */ +#define BLOCK_def -11 +/* not used in code but consistent with type in perl hash */ +#define BLOCK_preformatted -12 +/* not used in code but consistent with type in perl hash */ +#define BLOCK_math -13 /* Types of brace command (CF_brace). */ +#define BRACE_arguments 1 +#define BRACE_noarg 0 #define BRACE_context -1 /* Can enclose paragraph breaks. */ #define BRACE_accent -2 -#define BRACE_style -3 -#define BRACE_other -4 +#define BRACE_style_other -3 +#define BRACE_style_code -5 +#define BRACE_style_no_code -6 +#define BRACE_other -7 +#define BRACE_special -8 +#define BRACE_inline -9 + +/* Types of internal commands (CF_internal). */ +#define INTERNAL_brace -1 #endif diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/conf.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/conf.c index 4d734942bb..5797e12853 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/conf.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/conf.c @@ -47,4 +47,5 @@ reset_conf (void) conf.show_menu = 1; conf.cpp_line_directives = 1; conf.ignore_space_after_braced_command_name = 1; + conf.doc_encoding_for_input_file_name = 1; } diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/conf.h b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/conf.h index 7efcb566b3..33ce3b7fbf 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/conf.h +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/conf.h @@ -20,6 +20,7 @@ typedef struct CONF { int show_menu; int cpp_line_directives; int ignore_space_after_braced_command_name; + int doc_encoding_for_input_file_name; } CONF; extern CONF conf; diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/context_stack.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/context_stack.c index b3fca7afc5..0ecd1dec6e 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/context_stack.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/context_stack.c @@ -19,6 +19,7 @@ #include "parser.h" static enum context *stack; +static enum command_id *commands_stack; static size_t top; /* One above last pushed context. */ static size_t space; @@ -29,20 +30,24 @@ reset_context_stack (void) } void -push_context (enum context c) +push_context (enum context c, enum command_id cmd) { if (top >= space) { stack = realloc (stack, (space += 5) * sizeof (enum context)); + commands_stack + = realloc (commands_stack, (space += 5) * sizeof (enum command_id)); } - debug (">>>>>>>>>>>>>>>>>PUSHING STACK AT %d -- %s", top, + debug (">>>>>>>>>>>>>>>>>PUSHING STACK AT %d -- %s @%s", top, c == ct_preformatted ? "preformatted" : c == ct_line ? "line" : c == ct_def ? "def" - : c == ct_menu ? "menu" - : ""); - stack[top++] = c; + : c == ct_brace_command ? "brace_command" + : "", command_name(cmd)); + stack[top] = c; + commands_stack[top] = cmd; + top++; } enum context @@ -64,6 +69,21 @@ current_context (void) return stack[top - 1]; } +enum command_id +current_context_command (void) +{ + int i; + + if (top == 0) + return CM_NONE; + for (i = top -1; i >= 0; i--) + { + if (commands_stack[i] != CM_NONE) + return commands_stack[i]; + } + return CM_NONE; +} + /* The valid regions are 'titlepage', 'copying', and 'documentdescription'. This stack isn't used that much. */ @@ -119,3 +139,28 @@ current_region (void) return region_stack[region_top - 1]; } + + +/* used for @kbd */ +int +in_preformatted_context_not_menu() +{ + int i; + + if (top == 0) + return 0; + for (i = top -1; i >= 0; i--) + { + enum context ct; + enum command_id cmd; + ct = stack[i]; + if (ct != ct_line && ct != ct_preformatted) + return 0; + cmd = commands_stack[i]; + if (command_data(cmd).flags & CF_block + && command_data(cmd).data != BLOCK_menu + && ct == ct_preformatted) + return 1; + } + return 0; +} diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/context_stack.h b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/context_stack.h index 9b4f93317c..3d8444e657 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/context_stack.h +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/context_stack.h @@ -24,26 +24,23 @@ enum context { ct_def, ct_preformatted, ct_rawpreformatted, - ct_menu, ct_math, - ct_footnote, - ct_caption, - ct_shortcaption, + ct_brace_command, ct_inlineraw }; /* Contexts where an empty line doesn't start a new paragraph. */ #define in_paragraph_context(c) \ !((c) == ct_math \ - || (c) == ct_menu \ || (c) == ct_def \ || (c) == ct_preformatted \ || (c) == ct_rawpreformatted \ || (c) == ct_inlineraw) -void push_context (enum context c); -enum context pop_context (); +void push_context (enum context c, enum command_id cmd); +enum context pop_context (void); enum context current_context (void); +enum command_id current_context_command (void); void reset_context_stack (void); @@ -53,4 +50,7 @@ ELEMENT *current_region (void); enum command_id current_region_cmd (void); void reset_region_stack (void); + + +int in_preformatted_context_not_menu(void); #endif diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/convert.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/convert.c index b932855c27..697f5a2bfb 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/convert.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/convert.c @@ -164,15 +164,6 @@ convert_to_texinfo_internal (ELEMENT *e, TEXT *result) } if (e->type == ET_bracketed) ADD("}"); - - // TODO: raw block command - if (command_flags (e) & CF_block) - { - ADD("@end "); - ADD(command_name(e->cmd)); - if (command_data(e->cmd).data != BLOCK_raw) - ADD("\n"); - } } return; diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/def.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/def.c index b2bddb205f..bea4544d14 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/def.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/def.c @@ -75,7 +75,6 @@ next_bracketed_or_word (ELEMENT *current, int *i) if (current->contents.list[*i]->type != ET_spaces && current->contents.list[*i]->type != ET_spaces_inserted && current->contents.list[*i]->type != ET_spaces_at_end - && current->contents.list[*i]->type != ET_empty_spaces_after_command && current->contents.list[*i]->type != ET_delimiter) break; (*i)++; @@ -98,7 +97,6 @@ next_bracketed_or_word_agg (ELEMENT *current, int *i) if (e->type == ET_spaces || e->type == ET_spaces_inserted || e->type == ET_spaces_at_end - || e->type == ET_empty_spaces_after_command || e->type == ET_delimiter) { if (num > 0) @@ -180,8 +178,6 @@ split_delimiters (ELEMENT *current, int starting_idx) if (e->type != ET_NONE || e->text.end == 0) continue; - if (e->type == ET_empty_spaces_after_command) - continue; p = e->text.text; while (1) @@ -274,11 +270,6 @@ parse_def (enum command_id command, ELEMENT *current) ret = malloc (sizeof (DEF_INFO)); memset (ret, 0, sizeof (DEF_INFO)); - if (current->contents.number > 0 - && (current->contents.list[0]->type == ET_empty_spaces_after_command - || current->contents.list[0]->type == ET_empty_line_after_command)) - contents_idx++; - split_def_args (current, contents_idx); /* Check for "def alias" - for example @defun for @deffn. */ diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/element_types.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/element_types.c index d76fcb481a..99d8dab9c2 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/element_types.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/element_types.c @@ -8,24 +8,19 @@ char *element_type_names[] = { "definfoenclose_command", "empty_line", "raw", -"last_raw_newline", -"empty_line_after_command", -"empty_spaces_after_command", +"ignorable_spaces_after_command", "spaces_at_end", -"empty_space_at_end_def_bracketed", -"space_at_end_block_command", -"empty_spaces_before_argument", -"empty_spaces_after_close_brace", -"empty_spaces_before_paragraph", -"preamble_text", +"spaces_after_close_brace", +"spaces_before_paragraph", +"text_before_beginning", "space_at_end_menu_node", -"after_description_line", +"after_menu_description_line", "spaces", "spaces_inserted", -"text_root", "document_root", "root_line", -"preamble", +"before_node_section", +"preamble_before_beginning", "preamble_before_setfilename", "paragraph", "preformatted", @@ -42,7 +37,10 @@ char *element_type_names[] = { "menu_entry_node", "menu_entry_description", "menu_comment", -"menu_star", +"internal_menu_star", +"internal_spaces_after_command", +"internal_spaces_before_argument", +"internal_spaces_before_brace_in_index", "macro_name", "macro_arg", "before_item", diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/element_types.h b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/element_types.h index 9a6fb59c9b..c18e6c5a6e 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/element_types.h +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/element_types.h @@ -11,24 +11,19 @@ ET_space_command_arg, ET_definfoenclose_command, ET_empty_line, ET_raw, -ET_last_raw_newline, -ET_empty_line_after_command, -ET_empty_spaces_after_command, +ET_ignorable_spaces_after_command, ET_spaces_at_end, -ET_empty_space_at_end_def_bracketed, -ET_space_at_end_block_command, -ET_empty_spaces_before_argument, -ET_empty_spaces_after_close_brace, -ET_empty_spaces_before_paragraph, -ET_preamble_text, +ET_spaces_after_close_brace, +ET_spaces_before_paragraph, +ET_text_before_beginning, ET_space_at_end_menu_node, -ET_after_description_line, +ET_after_menu_description_line, ET_spaces, ET_spaces_inserted, -ET_text_root, ET_document_root, ET_root_line, -ET_preamble, +ET_before_node_section, +ET_preamble_before_beginning, ET_preamble_before_setfilename, ET_paragraph, ET_preformatted, @@ -45,7 +40,10 @@ ET_menu_entry_separator, ET_menu_entry_node, ET_menu_entry_description, ET_menu_comment, -ET_menu_star, +ET_internal_menu_star, +ET_internal_spaces_after_command, +ET_internal_spaces_before_argument, +ET_internal_spaces_before_brace_in_index, ET_macro_name, ET_macro_arg, ET_before_item, diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/element_types.txt b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/element_types.txt index 68764f6af1..ee7034193a 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/element_types.txt +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/element_types.txt @@ -26,26 +26,21 @@ definfoenclose_command # For text elements empty_line raw -last_raw_newline -empty_line_after_command -empty_spaces_after_command +ignorable_spaces_after_command spaces_at_end -empty_space_at_end_def_bracketed -space_at_end_block_command -empty_spaces_before_argument -empty_spaces_after_close_brace -empty_spaces_before_paragraph -preamble_text +spaces_after_close_brace +spaces_before_paragraph +text_before_beginning space_at_end_menu_node -after_description_line +after_menu_description_line spaces spaces_inserted # Other special types -text_root document_root root_line -preamble +before_node_section +preamble_before_beginning preamble_before_setfilename paragraph preformatted @@ -64,7 +59,10 @@ menu_entry_node menu_entry_description menu_comment # Used internally -menu_star +internal_menu_star +internal_spaces_after_command +internal_spaces_before_argument +internal_spaces_before_brace_in_index macro_name macro_arg diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/end_line.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/end_line.c index 4556780052..87ca036edd 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/end_line.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/end_line.c @@ -1,5 +1,5 @@ /* end_line.c -- what to do at the end of a whole line of input */ -/* Copyright 2010-2019 Free Software Foundation, Inc. +/* Copyright 2010-2022 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -364,6 +364,8 @@ parse_line_command_args (ELEMENT *line_command) user_defined_command_data[new_cmd].flags |= CF_ALIAS; user_defined_command_data[new_cmd].data = existing_cmd; + user_defined_command_data[new_cmd].args_number + = command_data(existing_cmd).args_number; /* Note the data field is an int, existing_cmd is enum command_id, so would have problems if enum command_id were wider than an int. */ @@ -415,7 +417,8 @@ parse_line_command_args (ELEMENT *line_command) user_defined_command_data[new_cmd].flags |= (CF_INFOENCLOSE | CF_brace); - user_defined_command_data[new_cmd].data = BRACE_style; + user_defined_command_data[new_cmd].data = BRACE_style_other; + user_defined_command_data[new_cmd].args_number = 1; ADD_ARG(new_command); free (new_command); ADD_ARG(start); free (start); @@ -721,6 +724,7 @@ parse_line_command_args (ELEMENT *line_command) case CM_codequoteundirected: case CM_codequotebacktick: case CM_deftypefnnewline: + case CM_microtype: { if (!strcmp (line, "on") || !strcmp (line, "off")) { @@ -778,8 +782,8 @@ kdbinputstyle_invalid: case CM_headings: { if (!strcmp (line, "off") || !strcmp (line, "on") - || !strcmp (line, "double") || !strcmp (line, "singleafter") - || !strcmp (line, "doubleafter")) + || !strcmp (line, "single") || !strcmp (line, "double") + || !strcmp (line, "singleafter") || !strcmp (line, "doubleafter")) { ADD_ARG(line); } @@ -802,13 +806,11 @@ kdbinputstyle_invalid: } /* NODE->contents is the Texinfo for the specification of a node. This - function sets three fields on the returned object: + function sets two fields on the returned object: manual_content - Texinfo tree for a manual name extracted from the node specification. node_content - Texinfo tree for the node name on its own - normalized - a string with the node name after HTML node name - normalization is applied Objects returned from this function are used as an 'extra' key in a few places: the elements of a 'nodes_manuals' array (itself an extra key), @@ -1002,9 +1004,7 @@ parse_float_type (ELEMENT *current) ELEMENT * end_line_starting_block (ELEMENT *current) { - enum context c; - c = pop_context (); - if (c != ct_line) + if (pop_context () != ct_line) fatal ("line context expected"); if (current->parent->cmd == CM_multitable) @@ -1078,23 +1078,12 @@ end_line_starting_block (ELEMENT *current) if (counter_value (&count_remaining_args, current) != -1) counter_pop (&count_remaining_args); - /* Don't consider empty argument of block @-command as argument, - reparent them as contents. */ - if (current->args.list[0]->contents.number > 0 - && current->args.list[0]->contents.list[0]->type - == ET_empty_line_after_command) - { - ELEMENT *e = remove_from_contents (current->args.list[0], 0); - insert_into_contents (current, e, 0); - destroy_element (pop_element_from_args (current)); - } - if (current->cmd == CM_float) { char *type = ""; KEY_PAIR *k; EXTRA_FLOAT_TYPE *eft; - current->line_nr = line_nr; + current->source_info = current_source_info; if (current->args.number >= 2) { NODE_SPEC_EXTRA *float_label; @@ -1134,13 +1123,15 @@ end_line_starting_block (ELEMENT *current) if (current->args.number > 0 && current->args.list[0]->contents.number > 0) { + ELEMENT *g; if (current->args.list[0]->contents.number > 1) command_error (current, "superfluous argument to @%s", command_name(current->cmd)); - ELEMENT *g = current->args.list[0]->contents.list[0]; + g = current->args.list[0]->contents.list[0]; /* Check if @enumerate specification is either a single letter or a string of digits. */ - if (g->text.end == 1 && isalpha (g->text.text[0]) + if (g->text.end == 1 + && isalpha ((unsigned char) g->text.text[0]) || (g->text.end > 0 && !*(g->text.text + strspn (g->text.text, "0123456789")))) @@ -1165,7 +1156,7 @@ end_line_starting_block (ELEMENT *current) { ELEMENT *e = k->value; if (!(command_flags(e) & CF_brace) - || (command_data(e->cmd).data == 0)) + || (command_data(e->cmd).data == BRACE_noarg)) { command_error (current, "command @%s not accepting argument in brace " @@ -1244,10 +1235,21 @@ end_line_starting_block (ELEMENT *current) || current->args.list[0]->contents.number == 0)) { ELEMENT *e; + ELEMENT *block_line_arg; + if (last_args_child(current) + && last_args_child(current)->type == ET_block_line_arg) + { + block_line_arg = last_args_child(current); + } + else + { + block_line_arg = new_element (ET_block_line_arg); + insert_into_args (current, block_line_arg, 0); + } e = new_element (ET_command_as_argument_inserted); e->cmd = CM_bullet; - insert_into_args (current, e, 0); + insert_into_contents (block_line_arg, e, 0); add_extra_element (current, "command_as_argument", e); } else if (item_line_command (current->cmd) @@ -1268,7 +1270,7 @@ end_line_starting_block (ELEMENT *current) } } /* CF_blockitem */ - if (command_flags(current) & CF_menu) + if (command_data(current->cmd).data == BLOCK_menu) { /* Start reading a menu. Processing will continue in handle_menu in menus.c. */ @@ -1277,9 +1279,16 @@ end_line_starting_block (ELEMENT *current) add_to_element_contents (current, menu_comment); current = menu_comment; debug ("MENU_COMMENT OPEN"); - push_context (ct_preformatted); } - current = begin_preformatted (current); + if (command_data(current->cmd).data == BLOCK_format_raw + && format_expanded_p (command_name(current->cmd))) + { + ELEMENT *rawpreformatted = new_element (ET_rawpreformatted); + add_to_element_contents (current, rawpreformatted); + current = rawpreformatted; + } + if (command_data(current->cmd).data != BLOCK_raw) + current = begin_preformatted (current); return current; } @@ -1291,10 +1300,9 @@ end_line_misc_line (ELEMENT *current) { enum command_id cmd; int arg_type; - enum context c; ELEMENT *misc_cmd; char *end_command = 0; - enum command_id end_id; + enum command_id end_id = CM_NONE; int included_file = 0; isolate_last_space (current); @@ -1307,14 +1315,12 @@ end_line_misc_line (ELEMENT *current) arg_type = command_data(cmd).data; - /* Check 'line' is top of the context stack */ - c = pop_context (); - if (c != ct_line) + if (pop_context () != ct_line) fatal ("line context expected"); debug ("MISC END %s", command_name(cmd)); - if (arg_type > 0) + if (arg_type == LINE_specific) { ELEMENT *args = parse_line_command_args (current); if (args) @@ -1381,31 +1387,18 @@ end_line_misc_line (ELEMENT *current) free (end_command); end_command = 0; } } - if (end_command) - { - add_extra_string (current, "command_argument", - end_command); - } + /* If there is superfluous text after @end argument, set + superfluous_arg such that the error message triggered by an + unexpected @-command on the @end line is issued below. Note + that superfluous_arg may also be true if it was set above. */ if (end_command - && (superfluous_arg - || line[strspn (line, whitespace_chars)] != '\0')) - { - char *line, *line2; - line = convert_to_texinfo (current->args.list[0]); - - line2 = line; - line2 += strspn (line2, whitespace_chars); - free (read_command_name (&line2)); - command_error (current, - "superfluous argument to @end %s: " - "%s", end_command, line2); - superfluous_arg = 0; /* Don't issue another error - message below. */ - free (line); - } + && line[strspn (line, whitespace_chars)] != '\0') + superfluous_arg = 1; } } - else + /* if superfluous_arg is set there is a similar and somewhat + better error message below */ + else if (!superfluous_arg) { command_error (current, "bad argument to @end: %s", line); } @@ -1417,10 +1410,12 @@ end_line_misc_line (ELEMENT *current) else if (current->cmd == CM_include) { int status; - char *fullpath; + char *fullpath, *sys_filename; debug ("Include %s", text); - fullpath = locate_include_file (text); + sys_filename = encode_file_name (text); + fullpath = locate_include_file (sys_filename); + if (!fullpath) { command_error (current, @@ -1438,7 +1433,6 @@ end_line_misc_line (ELEMENT *current) } else included_file = 1; - free (fullpath); } } else if (current->cmd == CM_verbatiminclude) @@ -1498,6 +1492,8 @@ end_line_misc_line (ELEMENT *current) static char *known_encodings[] = { "shift_jis", "latin1", + "latin-1", + "utf8", 0 }; for (i = 0; (known_encodings[i]); i++) @@ -1516,11 +1512,16 @@ end_line_misc_line (ELEMENT *current) struct encoding_map { char *from; char *to; }; + /* The map mimics Encode::find_encoding()->name() result. + Even when the alias is not good, such as 'utf-8-strict' + for 'utf-8', use the same mapping for consistency with the + perl Parser */ static struct encoding_map map[] = { "utf-8", "utf-8-strict", "us-ascii", "ascii", "shift_jis", "shiftjis", - "latin1", "iso-8859-1" + "latin1", "iso-8859-1", + "latin-1", "iso-8859-1" }; for (i = 0; i < sizeof map / sizeof *map; i++) { @@ -1539,7 +1540,7 @@ end_line_misc_line (ELEMENT *current) { command_warn (current, "unrecognized encoding name `%s'", text); - /* Texinfo::Encoding calls Encode::Alias, so knows + /* the Perl Parser calls Encode::find_encoding, so knows about more encodings than what we know about here. TODO: Check when perl_encoding could be defined when texinfo_encoding isn't. @@ -1548,7 +1549,8 @@ end_line_misc_line (ELEMENT *current) } - /* Set input_encoding from perl_encoding */ + /* Set input_encoding from perl_encoding. In the perl parser, + lc(Encode::find_encoding()->mime_name()) is used */ input_encoding = 0; if (perl_encoding) { @@ -1560,12 +1562,11 @@ end_line_misc_line (ELEMENT *current) "utf-8-strict","utf-8", "ascii", "us-ascii", "shiftjis", "shift_jis", - "latin-1", "iso-8859-1", "iso-8859-1", "iso-8859-1", "iso-8859-2", "iso-8859-2", "iso-8859-15", "iso-8859-15", - "koi8-r", "koi8", - "koi8-u", "koi8", + "koi8-r", "koi8-r", + "koi8-u", "koi8-u", }; input_encoding = perl_encoding; for (i = 0; i < sizeof map / sizeof *map; i++) @@ -1600,7 +1601,7 @@ end_line_misc_line (ELEMENT *current) just check if the language code looks right. */ p = text; - while (isalpha (*p)) + while (isalpha ((unsigned char) *p)) p++; if (*p && *p != '_') { @@ -1625,7 +1626,7 @@ end_line_misc_line (ELEMENT *current) p = q; /* Language code should be of the form LL_CC, language code followed by country code. */ - while (isalpha (*p)) + while (isalpha ((unsigned char) *p)) p++; if (*p || p - q > 4) { @@ -1636,10 +1637,7 @@ end_line_misc_line (ELEMENT *current) } } } - - free (global_documentlanguage); - global_documentlanguage = strdup (text); - /* FIXME: check customization variable */ + set_documentlanguage (text); } } if (superfluous_arg) @@ -1648,16 +1646,15 @@ end_line_misc_line (ELEMENT *current) p = convert_to_texinfo (args_child_by_index(current, 0)); texi_line = p; - while (isspace (*texi_line)) + while (isspace ((unsigned char) *texi_line)) texi_line++; /* Trim leading and trailing whitespace. */ p1 = strchr (texi_line, '\0'); if (p1 > texi_line) { - while (p1 > texi_line && isspace (p1[-1])) + while (p1 > texi_line && isspace ((unsigned char) p1[-1])) p1--; - c = *p1; *p1 = '\0'; } command_error (current, "bad argument to @%s: %s", @@ -1695,9 +1692,9 @@ end_line_misc_line (ELEMENT *current) /* Copy the first 'node_content' array, to avoid the complication of it being referenced in two different places. This might be better with a separate function. */ + int i; label = new_element (0); - int i; for (i = 0; i<nodes_manuals[0]->node_content->contents.number; i++) @@ -1708,7 +1705,17 @@ end_line_misc_line (ELEMENT *current) } register_label (current, label); } - + if (current_part + && !lookup_extra (current_part, "part_associated_section")) + { + /* we only associate a part to the following node if the + part is not already associate to a sectioning command, + but the part can be associated to the sectioning command later + if a sectioning command follows the node. */ + add_extra_element (current, "node_preceding_part", current_part); + add_extra_element (current_part, "part_following_node", + current); + } current_node = current; } else if (current->cmd == CM_listoffloats) @@ -1750,6 +1757,18 @@ end_line_misc_line (ELEMENT *current) current->args.list[0]); current->type = ET_index_entry_command; } + /* if there is a brace command interrupting an index or subentry + command, replace the internal internal_spaces_before_brace_in_index + text type with its final type depending on whether there is + text after the brace command. */ + if ((command_flags(current) & CF_index_entry_command + || current->cmd == CM_subentry)) + { + if (lookup_extra (current, "sortas") + || lookup_extra (current, "seealso") + || lookup_extra (current, "seeentry")) + set_non_ignored_space_in_index_before_command(current->args.list[0]); + } } } @@ -1768,6 +1787,17 @@ end_line_misc_line (ELEMENT *current) if (command_data(end_id).data != BLOCK_conditional) { ELEMENT *closed_command; + /* here close some empty types. Typically empty preformatted + that would have been closed anyway in _close_commands, but + also other types (rawpreformatted, before_item), some which + may also have been closed anyway. */ + if (!current->cmd && current->type != ET_NONE + && (current->contents.number == 0) && current->parent) + { + current = current->parent; + destroy_element (pop_element_from_contents (current)); + debug ("popping at end command"); + } /* This closes tree elements (e.g. paragraphs) until we reach end_command. It can print an error if another block command is found first. */ @@ -1776,20 +1806,18 @@ end_line_misc_line (ELEMENT *current) destroy_element_and_children (end_elt); else { - add_extra_element (closed_command, "end_command", end_elt); close_command_cleanup (closed_command); add_to_element_contents (closed_command, end_elt); - if (command_flags(closed_command) & CF_menu - && current_context () == ct_menu) + if (command_data(closed_command->cmd).data == BLOCK_menu + && command_data(current_context_command()).data == BLOCK_menu) { ELEMENT *e; debug ("CLOSE menu but still in menu context"); e = new_element (ET_menu_comment); add_to_element_contents (current, e); current = e; - push_context (ct_preformatted); } } if (close_preformatted_command (end_id)) @@ -1827,7 +1855,8 @@ end_line_misc_line (ELEMENT *current) } else { - pop_context (); /* ct_line */; + if (pop_context () != ct_line) + fatal ("line context expected"); current = current->parent; @@ -1876,7 +1905,7 @@ end_line_misc_line (ELEMENT *current) current); if (current->cmd == CM_top) { - line_error_ext (1, ¤t_part->line_nr, + line_error_ext (1, ¤t_part->source_info, "@part should not be associated with @top"); } current_part = 0; @@ -1934,8 +1963,6 @@ end_line (ELEMENT *current) else current = current->parent; - pop_context (); //ct_preformatted - current = current->parent->parent; e = new_element (ET_menu_comment); add_to_element_contents (current, e); @@ -1945,12 +1972,11 @@ end_line (ELEMENT *current) add_to_element_contents (current, e); current = e; - e = new_element (ET_after_description_line); + e = new_element (ET_after_menu_description_line); text_append (&e->text, empty_line->text.text); destroy_element (empty_line); add_to_element_contents (current, e); - push_context (ct_preformatted); debug ("MENU: END DESCRIPTION, OPEN COMMENT"); } else if (in_paragraph_context (current_context ())) @@ -2036,14 +2062,13 @@ end_line (ELEMENT *current) current = last_contents_child(current); else { + ELEMENT *e; /* This should not happen */ bug ("description or menu comment not in preformatted"); - ELEMENT *e; e = new_element (ET_preformatted); add_to_element_contents (current, e); current = e; } - push_context (ct_preformatted); } else { @@ -2054,7 +2079,6 @@ end_line (ELEMENT *current) e = new_element (ET_preformatted); add_to_element_contents (current, e); current = e; - push_context (ct_preformatted); debug ("THEN MENU_COMMENT OPEN"); } { @@ -2123,6 +2147,9 @@ end_line (ELEMENT *current) free (stripped); } + /* in case there are no arguments at all, it needs to be called here. */ + abort_empty_line (¤t, NULL); + def_info = parse_def (def_command, current); /* Record the index entry if def_info is not empty. */ @@ -2166,8 +2193,9 @@ end_line (ELEMENT *current) || def_command == CM_deftypeivar || def_command == CM_deftypecv)) { - add_extra_string_dup (current->parent, "documentlanguage", - global_documentlanguage); + if (global_documentlanguage) + add_extra_string_dup (current->parent, "documentlanguage", + global_documentlanguage); } else { @@ -2197,55 +2225,10 @@ end_line (ELEMENT *current) current = end_line_starting_block (current); } - /* after an "@end verbatim" */ - else if (current->contents.number - && last_contents_child(current)->type == ET_empty_line_after_command - && contents_child_by_index(current, -2) - && contents_child_by_index(current, -2)->cmd == CM_verbatim) - { - /* - if we are after a @end verbatim, we must restart a preformatted if needed, - since there is no @end command explicitly associated to raw commands - it won't be done elsewhere. - */ - - current = begin_preformatted (current); - } else if (current->type == ET_line_arg) { current = end_line_misc_line (current); } - else if (current->contents.number == 1 - && current->contents.list[0]->type == ET_empty_line_after_command - || current->contents.number == 2 - && current->contents.list[0]->type == ET_empty_line_after_command - && (current->contents.list[1]->cmd == CM_c - || current->contents.list[1]->cmd == CM_comment)) - { - if (current->type == ET_preformatted - || current->type == ET_rawpreformatted) - { - /* Empty line after a @menu, or before a preformatted. Reparent - to the menu or other format. */ - ELEMENT *parent, *to_reparent; - - parent = current->parent; - if (parent->type == ET_menu_comment - && parent->contents.number == 1) - { - parent = parent->parent; - } - to_reparent = pop_element_from_contents (parent); - debug ("LINE AFTER COMMAND IN PREFORMATTED"); - while (current->contents.number > 0) - { - ELEMENT *e; - e = remove_from_contents (current, 0); - add_to_element_contents (parent, e); - } - add_to_element_contents (parent, to_reparent); - } - } /* 'line' or 'def' at top of "context stack" - this happens when line commands are nested (always incorrectly?) */ diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/errors.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/errors.c index 522bd3434d..fafaf9c9d4 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/errors.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/errors.c @@ -1,4 +1,4 @@ -/* Copyright 2010-2021 Free Software Foundation, Inc. +/* Copyright 2010-2022 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -28,6 +28,26 @@ #include "input.h" #include "text.h" +/* wrappers for asprintf and vasprintf */ +int +xvasprintf (char **ptr, const char *template, va_list ap) +{ + int ret; + ret = vasprintf (ptr, template, ap); + if (ret < 0) + abort (); /* out of memory */ + return ret; +} + +int +xasprintf (char **ptr, const char *template, ...) +{ + va_list v; + va_start (v, template); + return xvasprintf (ptr, template, v); +} + + void bug (char *message) { fprintf (stderr, "texi2any (XS parser): bug: %s\n", message); @@ -40,25 +60,19 @@ void fatal (char *message) } -typedef struct { - char *message; - enum error_type type; - LINE_NR line_nr; -} ERROR_MESSAGE; - -static ERROR_MESSAGE *error_list = 0; -static size_t error_number = 0; +ERROR_MESSAGE *error_list = 0; +size_t error_number = 0; static size_t error_space = 0; static void -line_error_internal (enum error_type type, LINE_NR *cmd_line_nr, +line_error_internal (enum error_type type, SOURCE_INFO *cmd_source_info, char *format, va_list v) { char *message; #ifdef ENABLE_NLS - vasprintf (&message, gettext(format), v); + xvasprintf (&message, gettext(format), v); #else - vasprintf (&message, format, v); + xvasprintf (&message, format, v); #endif if (!message) fatal ("vasprintf failed"); @@ -70,25 +84,25 @@ line_error_internal (enum error_type type, LINE_NR *cmd_line_nr, error_list[error_number].message = message; error_list[error_number].type = type; - if (cmd_line_nr) + if (cmd_source_info) { - if (cmd_line_nr->line_nr) - error_list[error_number++].line_nr = *cmd_line_nr; + if (cmd_source_info->line_nr) + error_list[error_number++].source_info = *cmd_source_info; else - error_list[error_number++].line_nr = line_nr; + error_list[error_number++].source_info = current_source_info; } else - error_list[error_number++].line_nr = line_nr; + error_list[error_number++].source_info = current_source_info; } void -line_error_ext (enum error_type type, LINE_NR *cmd_line_nr, +line_error_ext (enum error_type type, SOURCE_INFO *cmd_source_info, char *format, ...) { va_list v; va_start (v, format); - line_error_internal (type, cmd_line_nr, format, v); + line_error_internal (type, cmd_source_info, format, v); } void @@ -115,7 +129,7 @@ command_warn (ELEMENT *e, char *format, ...) va_list v; va_start (v, format); - line_error_internal (warning, &e->line_nr, format, v); + line_error_internal (warning, &e->source_info, format, v); } void @@ -124,7 +138,7 @@ command_error (ELEMENT *e, char *format, ...) va_list v; va_start (v, format); - line_error_internal (error, &e->line_nr, format, v); + line_error_internal (error, &e->source_info, format, v); } void @@ -142,12 +156,13 @@ bug_message_internal (char *format, va_list v) fprintf (stderr, "You found a bug: "); vfprintf (stderr, format, v); fprintf (stderr, "\n"); - if (line_nr.file_name) + if (current_source_info.file_name) { fprintf (stderr, - "last location %s:%d", line_nr.file_name, line_nr.line_nr); - if (line_nr.macro) - fprintf (stderr, " (possibly involving @%s)", line_nr.macro); + "last location %s:%d", current_source_info.file_name, + current_source_info.line_nr); + if (current_source_info.macro) + fprintf (stderr, " (possibly involving @%s)", current_source_info.macro); fprintf (stderr, "\n"); } exit (1); @@ -161,94 +176,3 @@ bug_message (char *format, ...) va_start (v, format); bug_message_internal (format, v); } - -static int indent = 0; - -/* Output INDENT spaces. */ -static void -dump_indent (TEXT *text) -{ - int i; - - for (i = 0; i < indent; i++) - text_append_n (text, " ", 1); -} - -/* Ouput S escaping single quotes and backslashes, so that - Perl can read it in when it is surrounded by single quotes. */ -void -dump_string (char *s, TEXT *text) -{ - while (*s) - { - if (*s == '\'' - || *s == '\\') - text_append_n (text, "\\", 1); - text_append_n (text, s++, 1); - } -} - -static void -dump_line_nr (LINE_NR *line_nr, TEXT *text) -{ - text_append_n (text, "{\n", 2); - indent += 2; - - dump_indent (text); - text_printf (text, "'file_name' => '%s',\n", - line_nr->file_name ? - line_nr->file_name : ""); - - if (line_nr->line_nr) - { - dump_indent (text); - text_append (text, "'line_nr' => "); - text_printf (text, "%d", line_nr->line_nr); - text_append (text, ",\n"); - } - - /* TODO: macro. */ - if (line_nr->macro) - { - dump_indent (text); - text_append (text, "'macro' => "); - text_printf (text, "'%s'", line_nr->macro); - text_append (text, ",\n"); - } - else - { - dump_indent (text); - text_append (text, "'macro' => ''\n"); - } - - - indent -= 2; - dump_indent (text); - text_append_n (text, "},\n", 3); -} - -char * -dump_errors (void) -{ - int i; - static TEXT t; - - text_reset (&t); - text_append (&t, "$ERRORS = [\n"); - for (i = 0; i < error_number; i++) - { - text_append (&t, "{ 'message' =>\n'"); - dump_string (error_list[i].message, &t); - text_append (&t, "',\n"); - text_printf (&t, "'type' => '%s',", error_list[i].type == error ? "error" - : "warning"); - text_append (&t, "'line_nr' => "); - dump_line_nr (&error_list[i].line_nr, &t); - text_append (&t, "},\n"); - } - text_append (&t, "];\n"); - - return t.text; -} - - diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/errors.h b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/errors.h index 733d1372a5..b3f8ad4f35 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/errors.h +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/errors.h @@ -3,6 +3,10 @@ #define ERRORS_H #include "tree_types.h" +#include <stdarg.h> + +int xasprintf (char **ptr, const char *template, ...); +int xvasprintf (char **ptr, const char *template, va_list ap); void fatal (char *); void bug (char *); @@ -14,9 +18,17 @@ void line_warn (char *format, ...); void command_error (ELEMENT *e, char *format, ...); void command_warn (ELEMENT *e, char *format, ...); void wipe_errors (void); -void line_error_ext (enum error_type type, LINE_NR *cmd_line_nr, +void line_error_ext (enum error_type type, SOURCE_INFO *cmd_source_info, char *format, ...); void bug_message (char *format, ...); -char *dump_errors (void); +typedef struct { + char *message; + enum error_type type; + SOURCE_INFO source_info; +} ERROR_MESSAGE; + +extern ERROR_MESSAGE *error_list; +extern size_t error_number; + #endif diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/handle_commands.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/handle_commands.c index fa3ce138f3..94c95eb69f 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/handle_commands.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/handle_commands.c @@ -55,8 +55,7 @@ check_no_text (ELEMENT *current) after_paragraph = 1; break; } - else if (t == ET_preformatted - || t == ET_rawpreformatted) + else if (t == ET_preformatted) { for (j = 0; j < f->contents.number; j++) { @@ -78,7 +77,7 @@ check_no_text (ELEMENT *current) return after_paragraph; } -/* noarg skipspace */ +/* symbol skipspace other */ ELEMENT * handle_other_command (ELEMENT *current, char **line_inout, enum command_id cmd, int *status) @@ -90,20 +89,36 @@ handle_other_command (ELEMENT *current, char **line_inout, *status = STILL_MORE_TO_PROCESS; arg_spec = command_data(cmd).data; - if (arg_spec == OTHER_noarg) + if (arg_spec != NOBRACE_skipspace) { - if (command_data(cmd).flags & CF_in_heading) + misc = new_element (ET_NONE); + misc->cmd = cmd; + add_to_element_contents (current, misc); + if (command_data(cmd).flags & CF_in_heading_spec + && !(command_data(current_context_command()).flags & CF_heading_spec)) { line_error ("@%s should only appear in heading or footing", command_name(cmd)); } - misc = new_element (ET_NONE); - misc->cmd = cmd; - add_to_element_contents (current, misc); - register_global_command (misc); - if (close_preformatted_command(cmd)) - current = begin_preformatted (current); + if (arg_spec == NOBRACE_symbol) + { + if (cmd == CM_BACKSLASH && current_context () != ct_math) + { + line_warn ("@\\ should only appear in math context"); + } + if (cmd == CM_NEWLINE) + { + current = end_line (current); + *status = GET_A_NEW_LINE; + } + } + else /* NOBRACE_other */ + { + register_global_command (misc); + if (close_preformatted_command(cmd)) + current = begin_preformatted (current); + } } else { @@ -148,88 +163,78 @@ handle_other_command (ELEMENT *current, char **line_inout, /* In a @multitable */ else if ((parent = item_multitable_parent (current))) { - if (cmd != CM_item && cmd != CM_headitem - && cmd != CM_tab) - { - line_error ("@%s not meaningful inside @%s block", - command_name(cmd), - command_name(parent->cmd)); - } + int max_columns = 0; + KEY_PAIR *prototypes; + + prototypes = lookup_extra (parent, "prototypes"); + if (prototypes) + max_columns = prototypes->value->contents.number; else { - int max_columns = 0; - KEY_PAIR *prototypes; - - prototypes = lookup_extra (parent, "prototypes"); + prototypes = lookup_extra(parent, "columnfractions"); if (prototypes) - max_columns = prototypes->value->contents.number; - else { - prototypes = lookup_extra(parent, "columnfractions"); + prototypes = lookup_extra((ELEMENT *) prototypes->value, + "misc_args"); if (prototypes) - { - prototypes = lookup_extra((ELEMENT *) prototypes->value, - "misc_args"); - if (prototypes) - max_columns = prototypes->value->contents.number; - } + max_columns = prototypes->value->contents.number; } + } - if (max_columns == 0) - { - line_warn ("@%s in empty multitable", - command_name(cmd)); - } - else if (cmd == CM_tab) + if (max_columns == 0) + { + line_warn ("@%s in empty multitable", + command_name(cmd)); + } + else if (cmd == CM_tab) + { + ELEMENT *row; + row = last_contents_child (parent); + if (row->type == ET_before_item) + line_error ("@tab before @item"); + else if (counter_value (&count_cells, row) + >= max_columns) { - ELEMENT *row; - row = last_contents_child (parent); - if (row->type == ET_before_item) - line_error ("@tab before @item"); - else if (counter_value (&count_cells, row) - >= max_columns) - { - line_error ("too many columns in multitable item" - " (max %d)", max_columns); - } - else - { - counter_inc (&count_cells); - misc = new_element (ET_NONE); - misc->cmd = cmd; - add_to_element_contents (row, misc); - current = misc; - debug ("TAB"); - - add_extra_integer (current, "cell_number", - counter_value (&count_cells, row)); - } + line_error ("too many columns in multitable item" + " (max %d)", max_columns); } - else /* @item or @headitem */ + else { - ELEMENT *row; - - debug ("ROW"); - row = new_element (ET_row); - add_to_element_contents (parent, row); - - /* Note that the "row_number" extra value, - isn't actually used anywhere at present. */ - add_extra_integer (row, "row_number", - parent->contents.number - 1); - + counter_inc (&count_cells); misc = new_element (ET_NONE); misc->cmd = cmd; add_to_element_contents (row, misc); current = misc; + debug ("TAB"); - if (counter_value (&count_cells, parent) != -1) - counter_pop (&count_cells); - counter_push (&count_cells, row, 1); add_extra_integer (current, "cell_number", counter_value (&count_cells, row)); } } + else /* @item or @headitem */ + { + ELEMENT *row; + + debug ("ROW"); + row = new_element (ET_row); + add_to_element_contents (parent, row); + + /* Note that the "row_number" extra value, + isn't actually used anywhere at present. */ + add_extra_integer (row, "row_number", + parent->contents.number - 1); + + misc = new_element (ET_NONE); + misc->cmd = cmd; + add_to_element_contents (row, misc); + current = misc; + + if (counter_value (&count_cells, parent) != -1) + counter_pop (&count_cells); + counter_push (&count_cells, row, 1); + add_extra_integer (current, "cell_number", + counter_value (&count_cells, row)); + } current = begin_preformatted (current); } /* In @multitable */ else if (cmd == CM_tab) @@ -244,61 +249,18 @@ handle_other_command (ELEMENT *current, char **line_inout, current = begin_preformatted (current); } if (misc) - misc->line_nr = line_nr; + misc->source_info = current_source_info; } else { misc = new_element (ET_NONE); misc->cmd = cmd; - misc->line_nr = line_nr; + misc->source_info = current_source_info; add_to_element_contents (current, misc); } - start_empty_line_after_command (current, &line, misc); - if (cmd == CM_indent || cmd == CM_noindent) - { - /* Start a new paragraph if not in one already. */ - int spaces; - ELEMENT *paragraph; - - /* Check if if we should change an ET_empty_line_after_command - element to ET_empty_spaces_after_command by looking ahead - to see what comes next. */ - if (!strchr (line, '\n')) - { - char *line2; - input_push_text (strdup (line), 0); - line2 = new_line (); - if (line2) - line = line2; - } - spaces = strspn (line, whitespace_chars); - if (spaces > 0) - { - char saved = line[spaces]; - line[spaces] = '\0'; - current = merge_text (current, line); - line[spaces] = saved; - line += spaces; - } - if (*line - && last_contents_child(current)->type - == ET_empty_line_after_command) - { - last_contents_child(current)->type - = ET_empty_spaces_after_command; - } - paragraph = begin_paragraph (current); - if (paragraph) - current = paragraph; - if (!*line) - { - *status = GET_A_NEW_LINE; - goto funexit; - } - } + start_empty_line_after_command (current, &line, 0); } -funexit: *line_inout = line; return current; } @@ -320,17 +282,10 @@ handle_line_command (ELEMENT *current, char **line_inout, { ELEMENT *closed_elt; /* Not used */ current = close_commands (current, 0, &closed_elt, cmd); - if (current->type == ET_text_root) - { - if (cmd != CM_bye) - { - /* Use document_root when we have nodes or sections. */ - ELEMENT *new_root = new_element (ET_document_root); - add_to_element_contents (new_root, current); - current = new_root; - } - } - else + /* if parse_texi_line is called on a line with a node/section then + it will directly be in the root_line, otherwise it is not directly + in the root, but in another container */ + if (current->type != ET_root_line) { current = current->parent; if (!current) @@ -339,14 +294,14 @@ handle_line_command (ELEMENT *current, char **line_inout, } /* Look up information about this command ( skipline text - line lineraw (a number) ). */ + line lineraw specific ). */ arg_spec = command_data(cmd).data; /* All the cases using the raw line. TODO: I don't understand what the difference is between these. LINE_skipline is used where the command takes no argument at all. */ if (arg_spec == LINE_skipline || arg_spec == LINE_lineraw - || arg_spec == LINE_special) + || arg_spec == LINE_special) { ELEMENT *args = 0; enum command_id equivalent_cmd = 0; @@ -375,16 +330,16 @@ handle_line_command (ELEMENT *current, char **line_inout, if (!strchr (line, '\n')) { char *line2; - LINE_NR save_ln; + SOURCE_INFO save_src_info; input_push_text (strdup (line), 0); - save_ln = line_nr; + save_src_info = current_source_info; line2 = new_line (); if (line2) { line = line2; - line_nr = save_ln; + current_source_info = save_src_info; } } @@ -443,22 +398,19 @@ handle_line_command (ELEMENT *current, char **line_inout, destroy_element_and_children (misc); misc = new_element (ET_NONE); misc->cmd = equivalent_cmd; - misc->line_nr = line_nr; + misc->source_info = current_source_info; line_args = new_element (ET_line_arg); add_to_element_args (misc, line_args); add_extra_misc_args (misc, "misc_args", args); - add_extra_string_dup (misc, "spaces_before_argument", " "); + add_extra_string_dup (line_args, "spaces_after_argument", "\n"); + e = new_element (ET_NONE); text_append (&e->text, arg); add_to_element_contents (line_args, e); - e = new_element (ET_spaces_at_end); - text_append_n (&e->text, "\n", 1); - add_to_element_contents (line_args, e); - add_to_element_contents (current, misc); } else @@ -498,10 +450,6 @@ handle_line_command (ELEMENT *current, char **line_inout, { global_info.sections_level--; } - else if (cmd == CM_novalidate) - { - global_info.novalidate = 1; - } if (misc) register_global_command (misc); @@ -544,7 +492,7 @@ handle_line_command (ELEMENT *current, char **line_inout, } misc = new_element (ET_NONE); misc->cmd = (cmd == CM_item_LINE) ? CM_item : CM_itemx; - misc->line_nr = line_nr; + misc->source_info = current_source_info; add_to_element_contents (current, misc); } else @@ -552,7 +500,7 @@ handle_line_command (ELEMENT *current, char **line_inout, /* Add to contents */ misc = new_element (ET_NONE); misc->cmd = cmd; - misc->line_nr = line_nr; + misc->source_info = current_source_info; if (cmd == CM_subentry) { @@ -588,7 +536,7 @@ handle_line_command (ELEMENT *current, char **line_inout, add_to_element_contents (current, misc); - if (command_data(cmd).flags & CF_sectioning) + if (command_data(cmd).flags & CF_sectioning_heading) { if (global_info.sections_level) { @@ -604,6 +552,7 @@ handle_line_command (ELEMENT *current, char **line_inout, char *base_name; int base_len; int after_paragraph; + char *val; /* Find the command with "x" stripped from the end, e.g. deffnx -> deffn. */ @@ -621,8 +570,14 @@ handle_line_command (ELEMENT *current, char **line_inout, add_extra_string (misc, "def_command", base_name); after_paragraph = check_no_text (current); - push_context (ct_def); + push_context (ct_def, cmd); misc->type = ET_def_line; + + /* Check txidefnamenospace flag */ + val = fetch_value ("txidefnamenospace"); + if (val) + add_extra_integer (misc, "omit_def_name_space", 1); + if (current->cmd == base_command) { ELEMENT *e = pop_element_from_contents (current); @@ -647,15 +602,17 @@ handle_line_command (ELEMENT *current, char **line_inout, arg = new_element (ET_line_arg); add_to_element_args (current, arg); - if (cmd == CM_node) + /* LINE_specific commands arguments are handled in a specific way. + The only other line commands that have more than one argument is + node, so the following condition only applies to node */ + if (command_data (current->cmd).data != LINE_specific + && command_data (current->cmd).args_number > 1) { - /* At most three comma-separated arguments to @node. This - is the only (non-block) line command taking comma-separated - arguments. Its arguments will be gathered the same as - those of some block line commands and brace commands. */ - counter_push (&count_remaining_args, current, 3); + counter_push (&count_remaining_args, + current, + command_data (current->cmd).args_number - 1); } - else if (cmd == CM_author) + if (cmd == CM_author) { ELEMENT *parent = current; int found = 0; @@ -700,7 +657,7 @@ handle_line_command (ELEMENT *current, char **line_inout, /* add 'line' to context_stack. This will be the case while we read the argument on this line. */ if (!(command_data(cmd).flags & CF_def)) - push_context (ct_line); + push_context (ct_line, cmd); start_empty_line_after_command (current, &line, misc); } @@ -726,6 +683,7 @@ static struct expanded_format expanded_formats[] = { "tex", 0, "xml", 0, "info", 1, + "latex", 0, }; void @@ -811,16 +769,19 @@ handle_block_command (ELEMENT *current, char **line_inout, { p += strspn (p, whitespace_chars); /* Check for a comment at the end of the line. */ - if (memcmp (p, "@c", 2) == 0) + if (*p) { - p += 2; - if (memcmp (p, "omment", 6) == 0) - p += 7; - if (*p && *p != '@' && !strchr (whitespace_chars, *p)) - goto bad_value; /* @c or @comment not terminated. */ + if (memcmp (p, "@c", 2) == 0) + { + p += 2; + if (memcmp (p, "omment", 6) == 0) + p += 7; + if (*p && *p != '@' && !strchr (whitespace_chars, *p)) + goto bad_value; /* @c or @comment not terminated. */ + } + else + goto bad_value; /* Trailing characters on line. */ } - else if (*p) - goto bad_value; /* Trailing characters on line. */ } if (1) { @@ -897,7 +858,8 @@ handle_block_command (ELEMENT *current, char **line_inout, else { ELEMENT *block = 0; - if (flags & CF_menu + ELEMENT *bla; /* block line arg element */ + if (command_data(cmd).data == BLOCK_menu && (current->type == ET_menu_comment || current->type == ET_menu_entry_description)) { @@ -906,8 +868,6 @@ handle_block_command (ELEMENT *current, char **line_inout, if (current->contents.number == 0) destroy_element (pop_element_from_contents (menu)); - if (pop_context () != ct_preformatted) - fatal ("preformatted context expected"); if (menu->type == ET_menu_entry) menu = menu->parent; current = menu; @@ -916,19 +876,24 @@ handle_block_command (ELEMENT *current, char **line_inout, if (flags & CF_def) { ELEMENT *def_line; - push_context (ct_def); + push_context (ct_def, cmd); block = new_element (ET_NONE); block->cmd = cmd; - block->line_nr = line_nr; + block->source_info = current_source_info; add_to_element_contents (current, block); current = block; + def_line = new_element (ET_def_line); - def_line->line_nr = line_nr; + def_line->source_info = current_source_info; add_to_element_contents (current, def_line); current = def_line; add_extra_string_dup (current, "def_command", command_name(cmd)); add_extra_string_dup (current, "original_def_cmdname", command_name(cmd)); + /* Check txidefnamenospace flag */ + char *val = fetch_value ("txidefnamenospace"); + if (val) + add_extra_integer (current, "omit_def_name_space", 1); } else { @@ -940,115 +905,73 @@ handle_block_command (ELEMENT *current, char **line_inout, } /* Check if 'block args command' */ - if (command_data(cmd).data != BLOCK_raw) + if (command_data(cmd).flags & CF_preformatted) + push_context (ct_preformatted, cmd); + else if (cmd == CM_displaymath) + push_context (ct_math, cmd); + else if (command_data(cmd).data == BLOCK_format_raw) { - if (command_data(cmd).flags & CF_preformatted) - push_context (ct_preformatted); - else if (cmd == CM_displaymath) - push_context (ct_math); - else if (command_data(cmd).flags & CF_format_raw) + push_context (ct_rawpreformatted, cmd); + } + else if (command_data(cmd).data == BLOCK_region) + { + if (current_region_cmd ()) { - push_context (ct_rawpreformatted); - if (!format_expanded_p (command_name(cmd))) - { - ELEMENT *e; - enum command_id dummy; - char *line_dummy; + line_error ("region %s inside region %s is not allowed", + command_name(cmd), + command_name(current_region_cmd ())); + } + push_region (block); + } - e = new_element (ET_elided_block); - add_to_element_contents (current, e); - line_dummy = line; - while (!is_end_current_command (current, - &line_dummy, &dummy)) - { - line = new_line (); - if (!line) - { - line = ""; - break; - } - line_dummy = line; - } - e = new_element (ET_empty_line_after_command); - text_append_n (&e->text, "\n", 1); - add_to_element_contents (current, e); + if (command_data(cmd).data == BLOCK_menu) + { + push_context (ct_preformatted, cmd); - e = new_element (ET_empty_line); - text_append (&e->text, ""); - add_to_element_contents (current, e); - goto funexit; - } - } - else if (command_data(cmd).data == BLOCK_region) + if (cmd == CM_direntry) + add_to_contents_as_array (&global_info.dircategory_direntry, + block); + + if (current_node) { - if (current_region_cmd ()) + if (cmd == CM_direntry && conf.show_menu) { - line_error ("region %s inside region %s is not allowed", - command_name(cmd), - command_name(current_region_cmd ())); + line_warn ("@direntry after first node"); } - push_region (block); - } - - if (command_data(cmd).flags & CF_menu) - { - if (current_context () == ct_preformatted) - push_context (ct_preformatted); - else - push_context (ct_menu); - - if (cmd == CM_direntry) - add_to_contents_as_array (&global_info.dircategory_direntry, - block); - - if (current_node) + else if (cmd == CM_menu) { - if (cmd == CM_direntry && conf.show_menu) - { - line_warn ("@direntry after first node"); - } - else if (cmd == CM_menu) - { - if (!(command_flags(current->parent) & CF_root)) - line_warn ("@menu in invalid context"); - /* Add to array of menus for current node. Currently - done in Perl code. */ - } + if (!(command_flags(current->parent) & CF_root)) + line_warn ("@menu in invalid context"); + /* Add to array of menus for current node. Currently + done in Perl code. */ } } + } + + if (cmd == CM_itemize || cmd == CM_enumerate) + counter_push (&count_items, current, 0); - if (cmd == CM_itemize || cmd == CM_enumerate) - counter_push (&count_items, current, 0); - /* Note that no equivalent thing is done in the Perl code, because - 'item_count' is assumed to start at 0. */ - - { - ELEMENT *bla = new_element (ET_block_line_arg); - add_to_element_args (current, bla); - - if (command_data (current->cmd).data > 1) - { - counter_push (&count_remaining_args, - current, - command_data (current->cmd).data - 1); - } - else if (command_data (current->cmd).data == BLOCK_variadic) - { - /* Unlimited args */ - counter_push (&count_remaining_args, current, - COUNTER_VARIADIC); - } - - current = bla; - if (!(command_data(cmd).flags & CF_def)) - push_context (ct_line); - - /* Note that an ET_empty_line_after_command gets reparented in the - contents in 'end_line'. */ - - } + bla = new_element (ET_block_line_arg); + add_to_element_args (current, bla); + + if (command_data (current->cmd).args_number > 1) + { + counter_push (&count_remaining_args, + current, + command_data (current->cmd).args_number - 1); + } + else if (command_data (current->cmd).flags & CF_variadic) + { + /* Unlimited args */ + counter_push (&count_remaining_args, current, + COUNTER_VARIADIC); } - block->line_nr = line_nr; + + current = bla; + if (!(command_data(cmd).flags & CF_def)) + push_context (ct_line, cmd); + + block->source_info = current_source_info; register_global_command (block); start_empty_line_after_command (current, &line, block); } @@ -1070,7 +993,7 @@ handle_brace_command (ELEMENT *current, char **line_inout, enum command_id cmd) /* The line number information is only ever used for brace commands if the command is given with braces, but it's easier just to always store the information. */ - e->line_nr = line_nr; + e->source_info = current_source_info; add_to_element_contents (current, e); @@ -1092,28 +1015,10 @@ handle_brace_command (ELEMENT *current, char **line_inout, enum command_id cmd) } else if (cmd == CM_kbd) { - if (current_context () == ct_preformatted - && global_kbdinputstyle != kbd_distinct - || global_kbdinputstyle == kbd_code) + if (kbd_formatted_as_code(current)) { add_extra_integer (e, "code", 1); } - else if (global_kbdinputstyle == kbd_example) - { - /* TODO: Understand what is going on here. */ - ELEMENT *tmp = current->parent; - while (tmp->parent - && (command_flags(tmp->parent) & CF_brace) - && command_data(tmp->parent->cmd).data != BRACE_context) - { - if (command_flags(tmp->parent) & CF_code_style) - { - add_extra_integer (e, "code", 1); - break; - } - tmp = tmp->parent->parent; - } - } } else if (command_data(cmd).flags & CF_INFOENCLOSE) { diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/indices.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/indices.c index f1dbc521f5..537bb833b8 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/indices.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/indices.c @@ -1,4 +1,4 @@ -/* Copyright 2010-2019 Free Software Foundation, Inc. +/* Copyright 2010-2022 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -121,7 +121,7 @@ add_index (char *name, int in_code) idx = add_index_internal (name, in_code); /* For example, "rq" -> "rqindex". */ - asprintf (&cmdname, "%s%s", name, "index"); + xasprintf (&cmdname, "%s%s", name, "index"); add_index_command (cmdname, idx); free (cmdname); } @@ -296,6 +296,7 @@ enter_index_entry (enum command_id index_type_command, entry->content = content; entry->command = current; entry->number = idx->index_number; + entry->ignored_chars = global_info.ignored_chars; k = lookup_extra (current, "sortas"); if (k) @@ -324,6 +325,40 @@ enter_index_entry (enum command_id index_type_command, line_warn ("entry for index `%s' outside of any node", idx->name); } +/* turn spaces that are ignored before @-commands like @sortas{} and + @seeentry{} back to regular spaces if there is content after the @-command + */ +void +set_non_ignored_space_in_index_before_command (ELEMENT *content) +{ + ELEMENT *e; + ELEMENT *pending_spaces_element = 0; + int i; + for (i = 0; i < content->contents.number; i++) + { + /* could also be, but it does not seems to be needed here: + e = contents_child_by_index (content, i); */ + e = content->contents.list[i]; + if (e->type == ET_internal_spaces_before_brace_in_index) + { + pending_spaces_element = e; + /* set to "spaces_at_end" in case there are only spaces after */ + e->type = ET_spaces_at_end; + } + else if (pending_spaces_element + && ! (e->cmd == CM_sortas + || e->cmd == CM_seeentry + || e->cmd == CM_seealso + || e->type == ET_spaces_after_close_brace) + && (! check_space_element(e))) + { + pending_spaces_element->type = ET_NONE; + pending_spaces_element = 0; + } + } +} + + INDEX * ultimate_index (INDEX *index) diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/indices.h b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/indices.h index 043042d3e2..dc17890f39 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/indices.h +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/indices.h @@ -16,4 +16,5 @@ void enter_index_entry (enum command_id index_type_command, ELEMENT *content); INDEX *ultimate_index (INDEX *index); void wipe_indices (void); +void set_non_ignored_space_in_index_before_command (ELEMENT *content); #endif diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.c index f97edbfd4e..c8730b4d6a 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.c @@ -1,4 +1,4 @@ -/* Copyright 2010-2020 Free Software Foundation, Inc. +/* Copyright 2010-2022 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,8 +13,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#define _GNU_SOURCE - #include <config.h> #include <stdlib.h> @@ -45,18 +43,30 @@ typedef struct { enum input_type type; FILE *file; - LINE_NR line_nr; + SOURCE_INFO source_info; char *text; /* Input text to be parsed as Texinfo. */ char *ptext; /* How far we are through 'text'. Used to split 'text' into lines. */ } INPUT; +static char *input_pushback_string; + enum character_encoding input_encoding; +static char *input_encoding_name; +static iconv_t reverse_iconv; /* used in encode_file_name */ + void set_input_encoding (char *encoding) { + free (input_encoding_name); input_encoding_name = strdup (encoding); + if (reverse_iconv) + { + iconv_close (reverse_iconv); + reverse_iconv = (iconv_t) 0; + } + if (!strcasecmp (encoding, "utf-8")) input_encoding = ce_utf8; else if (!strcmp (encoding, "iso-8859-1") @@ -82,20 +92,7 @@ int input_number = 0; int input_space = 0; /* Current filename and line number. Used for reporting. */ -LINE_NR line_nr; - -/* Change the line number of filename of the top input source. Used to - record a #line directive. If FILENAME is non-null, it should hbae - been returned from save_string. */ -void -save_line_directive (int line_nr, char *filename) -{ - INPUT *top = &input_stack[input_number - 1]; - if (line_nr) - top->line_nr.line_nr = line_nr; - if (filename) - top->line_nr.file_name = filename; -} +SOURCE_INFO current_source_info; /* Collect text from the input sources until a newline is found. This is used instead of next_text when we need to be sure we get an entire line of @@ -164,16 +161,61 @@ text_buffer_iconv (TEXT *buf, iconv_t iconv_state, } +static char * +encode_with_iconv (iconv_t our_iconv, char *s) +{ + static TEXT t; + ICONV_CONST char *inptr; size_t bytes_left; + size_t iconv_ret; + + t.end = 0; + inptr = s; + bytes_left = strlen (s); + text_alloc (&t, 10); + + while (1) + { + iconv_ret = text_buffer_iconv (&t, our_iconv, + &inptr, &bytes_left); + + /* Make sure libiconv flushes out the last converted character. + This is required when the conversion is stateful, in which + case libiconv might not output the last character, waiting to + see whether it should be combined with the next one. */ + if (iconv_ret != (size_t) -1 + && text_buffer_iconv (&t, our_iconv, 0, 0) != (size_t) -1) + /* Success: all of input converted. */ + break; + + if (bytes_left == 0) + break; + + switch (errno) + { + case E2BIG: + text_alloc (&t, t.space + 20); + break; + case EILSEQ: + default: + fprintf(stderr, "%s:%d: encoding error at byte 0x%2x\n", + current_source_info.file_name, current_source_info.line_nr, + *(unsigned char *)inptr); + inptr++; bytes_left--; + break; + } + } + + t.text[t.end] = '\0'; + return strdup (t.text); +} + /* Return conversion of S according to input_encoding. This function frees S. */ static char * convert_to_utf8 (char *s) { iconv_t our_iconv = (iconv_t) -1; - static TEXT t; - ICONV_CONST char *inptr; size_t bytes_left; - size_t iconv_ret; - enum character_encoding enc; + char *ret; /* Convert from @documentencoding to UTF-8. It might be possible not to convert to UTF-8 and use an 8-bit encoding @@ -182,7 +224,8 @@ convert_to_utf8 (char *s) file, then we'd have to keep track of which strings needed the UTF-8 flag and which didn't. */ - /* Initialize conversions for the first time. */ + /* Initialize conversions for the first time. iconv_open returns + (iconv_t) -1 on failure so these should only be called once. */ if (iconv_validate_utf8 == (iconv_t) 0) iconv_validate_utf8 = iconv_open ("UTF-8", "UTF-8"); if (iconv_from_latin1 == (iconv_t) 0) @@ -231,55 +274,96 @@ convert_to_utf8 (char *s) return s; } - t.end = 0; - inptr = s; - bytes_left = strlen (s); - text_alloc (&t, 10); + ret = encode_with_iconv (our_iconv, s); + free (s); + return ret; +} - while (1) - { - iconv_ret = text_buffer_iconv (&t, our_iconv, - &inptr, &bytes_left); - /* Make sure libiconv flushes out the last converted character. - This is required when the conversion is stateful, in which - case libiconv might not output the last character, waiting to - see whether it should be combined with the next one. */ - if (iconv_ret != (size_t) -1 - && text_buffer_iconv (&t, our_iconv, 0, 0) != (size_t) -1) - /* Success: all of input converted. */ - break; +int doc_encoding_for_input_file_name = 1; +char *input_file_name_encoding = 0; +char *locale_encoding = 0; - if (bytes_left == 0) - break; +void +set_input_file_name_encoding (char *value) +{ + free (input_file_name_encoding); + input_file_name_encoding = value ? strdup (value) : 0; +} - switch (errno) +void +set_locale_encoding (char *value) +{ + free (locale_encoding); + locale_encoding = value ? strdup (value) : 0; +} + +/* Reverse the decoding of the filename to the input encoding, to retrieve + the bytes that were present in the original Texinfo file. Return + value is freed by free_small_strings. */ +char * +encode_file_name (char *filename) +{ + if (!reverse_iconv) + { + if (input_file_name_encoding) { - case E2BIG: - text_alloc (&t, t.space + 20); - break; - case EILSEQ: - default: - fprintf(stderr, "%s:%d: encoding error at byte 0x%2x\n", - line_nr.file_name, line_nr.line_nr, *(unsigned char *)inptr); - inptr++; bytes_left--; - break; + reverse_iconv = iconv_open (input_file_name_encoding, "UTF-8"); + } + else if (doc_encoding_for_input_file_name) + { + if (input_encoding != ce_utf8 && input_encoding_name) + { + reverse_iconv = iconv_open (input_encoding_name, "UTF-8"); + } + } + else if (locale_encoding) + { + reverse_iconv = iconv_open (locale_encoding, "UTF-8"); } } + if (reverse_iconv && reverse_iconv != (iconv_t) -1) + { + char *s, *conv; + conv = encode_with_iconv (reverse_iconv, filename); + s = save_string (conv); + free (conv); + return s; + } + else + { + return save_string (filename); + } +} - free (s); - t.text[t.end] = '\0'; - return strdup (t.text); +/* Change the line number of filename of the top input source. Used to + record a #line directive. */ +void +save_line_directive (int line_nr, char *filename) +{ + char *f = 0; + INPUT *top; + + if (filename) + f = encode_file_name (filename); + + top = &input_stack[input_number - 1]; + if (line_nr) + top->source_info.line_nr = line_nr; + if (filename) + top->source_info.file_name = f; } + + int expanding_macro (char *macro) { int i; for (i = 0; i < input_number; i++) { - if (input_stack[i].line_nr.macro - && !strcmp (input_stack[i].line_nr.macro, macro)) + if (input_stack[i].source_info.macro + && !strcmp (input_stack[i].source_info.macro, macro)) { return 1; } @@ -289,6 +373,15 @@ expanding_macro (char *macro) char *save_string (char *string); +void +input_pushback (char *string) +{ + if (input_pushback_string) + fprintf (stderr, + "texi2any (XS module): bug: input_pushback called twice\n"); + input_pushback_string = string; +} + /* Return value to be freed by caller. Return null if we are out of input. */ char * next_text (void) @@ -298,6 +391,14 @@ next_text (void) size_t n; FILE *input_file; + if (input_pushback_string) + { + char *s; + s = input_pushback_string; + input_pushback_string = 0; + return s; + } + while (input_number > 0) { /* Check for pending input. */ @@ -321,10 +422,10 @@ next_text (void) else i->ptext = p; /* The next time, we will pop the input source. */ - if (!i->line_nr.macro) - i->line_nr.line_nr++; + if (!i->source_info.macro) + i->source_info.line_nr++; - line_nr = i->line_nr; + current_source_info = i->source_info; return new; @@ -339,7 +440,7 @@ next_text (void) { /* Add a newline at the end of the file if one is missing. */ char *line2; - asprintf (&line2, "%s\n", line); + xasprintf (&line2, "%s\n", line); free (line); line = line2; } @@ -349,8 +450,8 @@ next_text (void) if (comment) *comment = '\0'; - i->line_nr.line_nr++; - line_nr = i->line_nr; + i->source_info.line_nr++; + current_source_info = i->source_info; return convert_to_utf8 (line); } @@ -370,7 +471,7 @@ next_text (void) { if (fclose (input_stack[input_number - 1].file) == EOF) fprintf (stderr, "error on closing %s: %s", - input_stack[input_number - 1].line_nr.file_name, + input_stack[input_number - 1].source_info.file_name, strerror (errno)); } } @@ -398,9 +499,9 @@ input_push (char *text, char *macro, char *filename, int line_number) if (!macro) line_number--; - input_stack[input_number].line_nr.line_nr = line_number; - input_stack[input_number].line_nr.file_name = save_string (filename); - input_stack[input_number].line_nr.macro = save_string (macro); + input_stack[input_number].source_info.line_nr = line_number; + input_stack[input_number].source_info.file_name = save_string (filename); + input_stack[input_number].source_info.macro = save_string (macro); input_number++; } @@ -455,9 +556,9 @@ input_push_text (char *text, char *macro) char *filename = 0; if (input_number > 0) { - filename = input_stack[input_number - 1].line_nr.file_name; + filename = input_stack[input_number - 1].source_info.file_name; } - input_push (text, macro, filename, line_nr.line_nr); + input_push (text, macro, filename, current_source_info.line_nr); } } @@ -520,6 +621,17 @@ add_include_directory (char *filename) filename[len - 1] = '\0'; } +void +clear_include_directories (void) +{ + int i; + for (i = 0; i < include_dirs_number; i++) + { + free (include_dirs[i]); + } + include_dirs_number = 0; +} + /* Return value to be freed by caller. */ char * locate_include_file (char *filename) @@ -528,11 +640,9 @@ locate_include_file (char *filename) struct stat dummy; int i, status; - /* Checks if filename is absolute or relative to current directory. - TODO: Could use macros in top-level config.h for this. */ - /* TODO: The Perl code (in Common.pm, 'locate_include_file') handles - a volume in a path (like "A:"), possibly more general treatment - with File::Spec module. */ + /* Checks if filename is absolute or relative to current directory. */ + /* Note: the Perl code (in Common.pm, 'locate_include_file') handles + a volume in a path (like "A:") using the File::Spec module. */ if (!memcmp (filename, "/", 1) || !memcmp (filename, "../", 3) || !memcmp (filename, "./", 2)) @@ -545,7 +655,7 @@ locate_include_file (char *filename) { for (i = 0; i < include_dirs_number; i++) { - asprintf (&fullpath, "%s/%s", include_dirs[i], filename); + xasprintf (&fullpath, "%s/%s", include_dirs[i], filename); status = stat (fullpath, &dummy); if (status == 0) return fullpath; @@ -560,11 +670,17 @@ locate_include_file (char *filename) int input_push_file (char *filename) { - FILE *stream; + FILE *stream = 0; + char *p, *q; - stream = fopen (filename, "r"); - if (!stream) - return errno; + if (!strcmp (filename, "-")) + stream = stdin; + else + { + stream = fopen (filename, "r"); + if (!stream) + return errno; + } if (input_number == input_space) { @@ -574,7 +690,6 @@ input_push_file (char *filename) } /* Strip off a leading directory path. */ - char *p, *q; p = 0; q = strchr (filename, '/'); while (q) @@ -589,9 +704,9 @@ input_push_file (char *filename) input_stack[input_number].type = IN_file; input_stack[input_number].file = stream; - input_stack[input_number].line_nr.file_name = filename; - input_stack[input_number].line_nr.line_nr = 0; - input_stack[input_number].line_nr.macro = 0; + input_stack[input_number].source_info.file_name = filename; + input_stack[input_number].source_info.line_nr = 0; + input_stack[input_number].source_info.macro = 0; input_stack[input_number].text = 0; input_stack[input_number].ptext = 0; input_number++; diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.h b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.h index 6a906c0b47..9cf758e030 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.h +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/input.h @@ -13,17 +13,29 @@ void input_push (char *text, char *macro, char *filename, int line_number); void input_push_text (char *line, char *macro); void input_push_text_with_line_nos (char *text, int starting); int input_push_file (char *filename); +void input_pushback (char *line); void input_reset_input_stack (void); int expanding_macro (char *macro); int top_file_index (void); + char *locate_include_file (char *filename); +char *encode_file_name (char *filename); void set_input_encoding (char *encoding); void add_include_directory (char *filename); +void clear_include_directories (void); char *save_string (char *string); void free_small_strings (void); -extern LINE_NR line_nr; +extern SOURCE_INFO current_source_info; extern int input_number; + +extern int doc_encoding_for_input_file_name; +extern char *input_file_name_encoding; +extern char *locale_encoding; + +void set_input_file_name_encoding (char *value); +void set_locale_encoding (char *value); + #endif diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/macro.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/macro.c index 292e4cc08a..e2b65432b1 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/macro.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/macro.c @@ -1,4 +1,4 @@ -/* Copyright 2010-2019 Free Software Foundation, Inc. +/* Copyright 2010-2022 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -13,8 +13,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#define _GNU_SOURCE - #include <config.h> #include <stdlib.h> #include <string.h> @@ -87,7 +85,7 @@ parse_macro_command_line (enum command_id cmd, char **line_inout, macro = new_element (ET_NONE); macro->cmd = cmd; - macro->line_nr = line_nr; + macro->source_info = current_source_info; add_extra_string (macro, "arg_line", strdup (line)); /* Note this extra value isn't used much, so it might be possible @@ -659,6 +657,23 @@ store_value (char *name, char *value) v->name = strdup (name); v->value = strdup (value); + + /* Internal Texinfo flag */ + if (!strncmp (name, "txi", 3)) + { + int val = (strcmp(value, "0") != 0); + if (!strcmp (name, "txiindexbackslashignore")) + global_info.ignored_chars.backslash = val; + else if (!strcmp (name, "txiindexhyphenignore")) + global_info.ignored_chars.hyphen = val; + else if (!strcmp (name, "txiindexlessthanignore")) + global_info.ignored_chars.lessthan = val; + else if (!strcmp (name, "txiindexatsignignore")) + global_info.ignored_chars.atsign = val; + + /* also: txicodequotebacktick, txicodequoteundirected, + txicommandconditionals. Deal with them here? */ + } } void @@ -673,6 +688,21 @@ clear_value (char *name) value_list[i].value[0] = '\0'; } } + /* Internal Texinfo flag */ + if (!strncmp (name, "txi", 3)) + { + if (!strcmp (name, "txiindexbackslashignore")) + global_info.ignored_chars.backslash = 0; + else if (!strcmp (name, "txiindexhyphenignore")) + global_info.ignored_chars.hyphen = 0; + else if (!strcmp (name, "txiindexlessthanignore")) + global_info.ignored_chars.lessthan = 0; + else if (!strcmp (name, "txiindexatsignignore")) + global_info.ignored_chars.atsign = 0; + + /* also: txicodequotebacktick, txicodequoteundirected, + txicommandconditionals. Deal with them here? */ + } } char * @@ -685,6 +715,9 @@ fetch_value (char *name) return value_list[i].value; } + /* special value always returned as 1 to mark that @ifcommandnotdefined + is implemented. Note that in most cases it is also set from perl + using the configuration passed to the parser */ if (!strcmp (name, "txicommandconditionals")) return "1"; return 0; diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/menus.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/menus.c index dce4b749c4..394f2edf5b 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/menus.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/menus.c @@ -51,7 +51,8 @@ register_extra_menu_entry_information (ELEMENT *current) isolate_last_space (arg); parsed_entry_node = parse_node_manual (arg); - if (!parsed_entry_node) + if (!parsed_entry_node->manual_content + && !parsed_entry_node->node_content) { if (conf.show_menu) line_error ("empty node name in menu entry"); @@ -77,14 +78,13 @@ enter_menu_entry_node (ELEMENT *current) description = new_element (ET_menu_entry_description); add_to_element_args (current, description); register_extra_menu_entry_information (current); - current->line_nr = line_nr; + current->source_info = current_source_info; remember_internal_xref (current); current = description; preformatted = new_element (ET_preformatted); add_to_element_contents (current, preformatted); current = preformatted; - push_context (ct_preformatted); return current; } @@ -111,16 +111,16 @@ handle_menu (ELEMENT **current_inout, char **line_inout) abort_empty_line (¤t, 0); line++; /* Past the '*'. */ - star = new_element (ET_menu_star); + star = new_element (ET_internal_menu_star); text_append (&star->text, "*"); add_to_element_contents (current, star); - /* The ET_menu_star element won't appear in the final tree. */ + /* The ET_internal_menu_star element won't appear in the final tree. */ } /* A space after a "*" at the beginning of a line. */ else if (strchr (whitespace_chars, *line) && current->contents.number > 0 - && last_contents_child(current)->type == ET_menu_star) + && last_contents_child(current)->type == ET_internal_menu_star) { ELEMENT *menu_entry, *leading_text, *entry_name; int leading_spaces; @@ -158,9 +158,6 @@ handle_menu (ELEMENT **current_inout, char **line_inout) current = current->parent->parent->parent; } - if (pop_context () != ct_preformatted) - fatal ("preformatted context expected"); - menu_entry = new_element (ET_menu_entry); leading_text = new_element (ET_menu_entry_leading_text); entry_name = new_element (ET_menu_entry_name); @@ -175,7 +172,7 @@ handle_menu (ELEMENT **current_inout, char **line_inout) } /* A "*" followed by anything other than a space. */ else if (current->contents.number > 0 - && last_contents_child(current)->type == ET_menu_star) + && last_contents_child(current)->type == ET_internal_menu_star) { debug ("ABORT MENU STAR"); last_contents_child(current)->type = ET_NONE; diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/parser.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/parser.c index 65498f0267..8a85a14c2e 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/parser.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/parser.c @@ -1,4 +1,4 @@ -/* Copyright 2010-2019 Free Software Foundation, Inc. +/* Copyright 2010-2022 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,11 +24,11 @@ #include "input.h" -const char *whitespace_chars = " \t\f\r\n"; +const char *whitespace_chars = " \t\v\f\r\n"; const char *digit_chars = "0123456789"; // [^\S\r\n] in Perl -const char *whitespace_chars_except_newline = " \t\f"; +const char *whitespace_chars_except_newline = " \t\v\f"; /* Check if the contents of S2 appear at S1). */ int @@ -48,10 +48,10 @@ read_command_name (char **ptr) char *ret = 0; q = p; - if (!isalnum (*q)) + if (!isalnum ((unsigned char) *q)) return 0; /* Invalid. */ - while (isalnum (*q) || *q == '-' || *q == '_') + while (isalnum ((unsigned char) *q) || *q == '-' || *q == '_') q++; ret = strndup (p, q - p); p = q; @@ -68,7 +68,7 @@ read_flag_name (char **ptr) char *ret = 0; q = p; - if (!isalnum (*q) && *q != '-' && *q != '_') + if (!isalnum ((unsigned char) *q) && *q != '-' && *q != '_') return 0; /* Invalid. */ while (!strchr (whitespace_chars, *q) @@ -87,6 +87,27 @@ element_type_name (ELEMENT *e) return element_type_names[(e)->type]; } +/* Return 1 if the element expansion is all whitespace */ +int +check_space_element (ELEMENT *e) +{ + if (!( + e->cmd == CM_SPACE + || e->cmd == CM_TAB + || e->cmd == CM_NEWLINE + || e->cmd == CM_c + || e->cmd == CM_comment + || e->cmd == CM_COLON + || (!e->cmd && !e->type && e->text.end == 0) + || (e->text.end > 0 + && !*(e->text.text + strspn (e->text.text, whitespace_chars))) + )) + { + return 0; + } + return 1; +} + /* Current node, section and part. */ @@ -136,20 +157,35 @@ COUNTER count_cells; GLOBAL_INFO global_info; char *global_clickstyle = 0; char *global_documentlanguage = 0; +int global_documentlanguage_fixed = 0; +int global_accept_internalvalue = 0; enum kbd_enum global_kbdinputstyle = kbd_distinct; +/* Set the document language unless it was set on the texi2any command line. */ void set_documentlanguage (char *value) { + if (!global_documentlanguage_fixed) + { + free (global_documentlanguage); + global_documentlanguage = value ? strdup (value) : 0; + } +} + +void +set_documentlanguage_override (char *value) +{ free (global_documentlanguage); - global_documentlanguage = strdup (value); + global_documentlanguage = value ? strdup (value) : 0; + global_documentlanguage_fixed = 1; } + void -set_novalidate (int value) +set_accept_internalvalue() { - global_info.novalidate = value; + global_accept_internalvalue = 1; } /* Record the information from a command of global effect. */ @@ -162,8 +198,8 @@ register_global_command (ELEMENT *current) if (command_data(cmd).flags & CF_global) { - if (!current->line_nr.line_nr) - current->line_nr = line_nr; + if (!current->source_info.line_nr) + current->source_info = current_source_info; switch (cmd) { #define GLOBAL_CASE(cmx) \ @@ -184,7 +220,7 @@ register_global_command (ELEMENT *current) GLOBAL_CASE(detailmenu); GLOBAL_CASE(part); - /* from Common.pm %document_settable_at_commands */ + /* from Common.pm %document_settable_multiple_at_commands */ GLOBAL_CASE(allowcodebreaks); GLOBAL_CASE(clickstyle); GLOBAL_CASE(codequotebacktick); @@ -198,6 +234,7 @@ register_global_command (ELEMENT *current) GLOBAL_CASE(frenchspacing); GLOBAL_CASE(headings); GLOBAL_CASE(kbdinputstyle); + GLOBAL_CASE(microtype); GLOBAL_CASE(paragraphindent); GLOBAL_CASE(shortcontents); GLOBAL_CASE(urefbreakstyle); @@ -214,8 +251,8 @@ register_global_command (ELEMENT *current) { ELEMENT **where = 0; - if (!current->line_nr.line_nr) - current->line_nr = line_nr; + if (!current->source_info.line_nr) + current->source_info = current_source_info; switch (cmd) { case CM_setfilename: @@ -253,6 +290,13 @@ register_global_command (ELEMENT *current) GLOBAL_UNIQUE_CASE(oddfootingmarks); GLOBAL_UNIQUE_CASE(shorttitlepage); GLOBAL_UNIQUE_CASE(title); + GLOBAL_UNIQUE_CASE(novalidate); + GLOBAL_UNIQUE_CASE(afourpaper); + GLOBAL_UNIQUE_CASE(afourlatex); + GLOBAL_UNIQUE_CASE(afourwide); + GLOBAL_UNIQUE_CASE(afivepaper); + GLOBAL_UNIQUE_CASE(bsixpaper); + GLOBAL_UNIQUE_CASE(smallbook); #undef GLOBAL_UNIQUE_CASE /* NOTE: Same list in api.c:build_global_info2 and wipe_global_info. */ default: @@ -277,9 +321,12 @@ void wipe_global_info (void) { free (global_clickstyle); - free (global_documentlanguage); global_clickstyle = strdup ("arrow"); - global_documentlanguage = strdup (""); + if (!global_documentlanguage_fixed) + { + free (global_documentlanguage); + global_documentlanguage = 0; + } global_kbdinputstyle = kbd_distinct; free (global_info.input_perl_encoding); @@ -312,54 +359,41 @@ wipe_global_info (void) GLOBAL_CASE(frenchspacing); GLOBAL_CASE(headings); GLOBAL_CASE(kbdinputstyle); + GLOBAL_CASE(microtype); GLOBAL_CASE(paragraphindent); GLOBAL_CASE(shortcontents); GLOBAL_CASE(urefbreakstyle); GLOBAL_CASE(xrefautomaticsectiontitle); #undef GLOBAL_CASE + + /* clear the rest of the fields */ memset (&global_info, 0, sizeof (global_info)); global_info.input_perl_encoding = strdup ("utf-8"); global_info.input_encoding_name = strdup ("utf-8"); } +ELEMENT * +setup_document_root_and_before_node_section () +{ + ELEMENT *before_node_section = new_element (ET_before_node_section); + ELEMENT *document_root = new_element (ET_document_root); + add_to_element_contents (document_root, before_node_section); + return before_node_section; +} + ELEMENT * -parse_texi_file (char *filename) +parse_texi_document (void) { - char *p, *q; char *linep, *line = 0; - ELEMENT *root = new_element (ET_text_root); - ELEMENT *preamble = 0; - char c; - - int status; - - status = input_push_file (filename); - if (status) - return 0; - - /* Strip off a leading directory path, by looking for the last - '/' in filename. */ - p = 0; - q = strchr (filename, '/'); - while (q) - { - p = q; - q = strchr (q + 1, '/'); - } - - if (p) - { - c = *p; - *p = '\0'; - add_include_directory (filename); - *p = c; - } + ELEMENT *before_node_section = setup_document_root_and_before_node_section (); + ELEMENT *preamble_before_beginning = 0; + ELEMENT *document_root = before_node_section->parent; - /* Put all lines up to a line starting "\input" inside a "preamble" - element. */ + /* Put all the empty lines up to a line starting "\input" inside a + "preamble_before_beginning" element. */ while (1) { ELEMENT *l; @@ -369,28 +403,28 @@ parse_texi_file (char *filename) if (!line) break; - linep = line; + linep = line; linep += strspn (linep, whitespace_chars); if (*linep && !looking_at (linep, "\\input")) { - /* This line is not part of the preamble. Shove back - into input stream. */ - input_push (line, 0, line_nr.file_name, line_nr.line_nr); + /* This line is not part of the preamble_before_beginning. + Push back into input stream. */ + input_pushback (line); break; } - if (!preamble) - preamble = new_element (ET_preamble); + if (!preamble_before_beginning) + preamble_before_beginning = new_element (ET_preamble_before_beginning); - l = new_element (ET_preamble_text); + l = new_element (ET_text_before_beginning); text_append (&l->text, line); - add_to_element_contents (preamble, l); + add_to_element_contents (preamble_before_beginning, l); } - if (preamble) - add_to_element_contents (root, preamble); + if (preamble_before_beginning) + add_to_element_contents (before_node_section, preamble_before_beginning); - return parse_texi (root); + return parse_texi (document_root, before_node_section); } @@ -399,7 +433,7 @@ begin_paragraph_p (ELEMENT *current) { return (current->type == ET_NONE /* "True for @-commands" */ || current->type == ET_before_item - || current->type == ET_text_root + || current->type == ET_before_node_section || current->type == ET_document_root || current->type == ET_brace_command_context) && in_paragraph_context (current_context ()); @@ -426,7 +460,7 @@ begin_paragraph (ELEMENT *current) if (child->type == ET_empty_line || child->type == ET_paragraph) break; - if (close_paragraph_command(child->cmd)) + if (command_data(child->cmd).flags & CF_close_paragraph) break; if (child->cmd == CM_indent || child->cmd == CM_noindent) @@ -455,32 +489,23 @@ begin_paragraph (ELEMENT *current) ELEMENT * begin_preformatted (ELEMENT *current) { - if (current_context() == ct_preformatted - || current_context() == ct_rawpreformatted) + if (current_context() == ct_preformatted) { - ELEMENT *e; - enum element_type et; - - if (current_context() == ct_preformatted) - et = ET_preformatted; - else - et = ET_rawpreformatted; - e = new_element (et); - add_to_element_contents (current, e); - current = e; - debug ("PREFORMATTED %s", et == ET_preformatted ? "preformatted" - : "rawpreformatted"); + ELEMENT *preformatted = new_element (ET_preformatted); + add_to_element_contents (current, preformatted); + current = preformatted; + debug ("PREFORMATTED"); } return current; } ELEMENT * end_paragraph (ELEMENT *current, - enum command_id closed_command, + enum command_id closed_block_command, enum command_id interrupting_command) { - current = close_all_style_commands (current, - closed_command, interrupting_command); + current = close_all_style_commands (current, closed_block_command, + interrupting_command); if (current->type == ET_paragraph) { debug ("CLOSE PARA"); @@ -492,17 +517,14 @@ end_paragraph (ELEMENT *current, ELEMENT * end_preformatted (ELEMENT *current, - enum command_id closed_command, + enum command_id closed_block_command, enum command_id interrupting_command) { - current = close_all_style_commands (current, - closed_command, interrupting_command); - if (current->type == ET_preformatted - || current->type == ET_rawpreformatted) + current = close_all_style_commands (current, closed_block_command, + interrupting_command); + if (current->type == ET_preformatted) { - debug ("CLOSE PREFORMATTED %s", - current->type == ET_preformatted ? "preformatted" - : "rawpreformatted"); + debug ("CLOSE PREFORMATTED"); if (current->contents.number == 0) { current = current->parent; @@ -529,10 +551,10 @@ merge_text (ELEMENT *current, char *text) char *additional = 0; if (last_child - && (last_child->type == ET_empty_line_after_command - || last_child->type == ET_empty_spaces_after_command - || last_child->type == ET_empty_spaces_before_argument - || last_child->type == ET_empty_spaces_after_close_brace)) + && (last_child->type == ET_ignorable_spaces_after_command + || last_child->type == ET_internal_spaces_after_command + || last_child->type == ET_internal_spaces_before_argument + || last_child->type == ET_spaces_after_close_brace)) { no_merge_with_following_text = 1; } @@ -558,16 +580,11 @@ merge_text (ELEMENT *current, char *text) if (last_child /* There is a difference between the text being defined and empty, and not defined at all. The latter is true for 'brace_command_arg' - elements. We need either to make sure that we initialize all elements + elements. We need either to make sure that we initialize all elements with text_append (&e->text, "") where we want merging with following - text, or treat as a special case here. - Unfortunately we can't make a special case for - ET_empty_spaces_before_argument, because abort_empty_line above - produces such an element that shouldn't be merged with. */ + text, or treat as a special case here. */ && (last_child->text.space > 0 - && !strchr (last_child->text.text, '\n') - ) /* || last_child->type == ET_empty_spaces_before_argument) */ - && last_child->cmd != CM_value + && !strchr (last_child->text.text, '\n')) && !no_merge_with_following_text) { /* Append text to contents */ @@ -600,19 +617,13 @@ abort_empty_line (ELEMENT **current_inout, char *additional_spaces) if (last_child && (last_child->type == ET_empty_line - || last_child->type == ET_empty_line_after_command - || last_child->type == ET_empty_spaces_before_argument - || last_child->type == ET_empty_spaces_after_close_brace)) + || last_child->type == ET_ignorable_spaces_after_command + || last_child->type == ET_internal_spaces_after_command + || last_child->type == ET_internal_spaces_before_argument + || last_child->type == ET_spaces_after_close_brace)) { - ELEMENT *owning_element = 0, *e; - KEY_PAIR *k; - retval = 1; - k = lookup_extra (last_child, "command"); - if (k) - owning_element = (ELEMENT *) k->value; - debug ("ABORT EMPTY %s additional text |%s| " "current |%s|", element_type_name(last_child), @@ -623,29 +634,28 @@ abort_empty_line (ELEMENT **current_inout, char *additional_spaces) /* Remove element altogether if it's empty. */ if (last_child->text.end == 0) { - e = pop_element_from_contents (current); + ELEMENT *e = pop_element_from_contents (current); destroy_element (e); } else if (last_child->type == ET_empty_line) { last_child->type = begin_paragraph_p (current) - ? ET_empty_spaces_before_paragraph : ET_NONE; + ? ET_spaces_before_paragraph : ET_NONE; } - else if (last_child->type == ET_empty_line_after_command - || last_child->type == ET_empty_spaces_before_argument) + else if (last_child->type == ET_internal_spaces_after_command + || last_child->type == ET_internal_spaces_before_argument) { - if (owning_element) - { - /* Remove element from main tree. */ - ELEMENT *e = pop_element_from_contents (current); - add_extra_string_dup (owning_element, "spaces_before_argument", - e->text.text); - destroy_element (e); - } - else - { - last_child->type = ET_empty_spaces_after_command; - } + /* Remove element from main tree. It will still be referenced in + the 'extra' hash as 'spaces_before_argument'. */ + ELEMENT *owning_element; + KEY_PAIR *k; + ELEMENT *e = pop_element_from_contents (current); + + k = lookup_extra (last_child, "spaces_associated_command"); + owning_element = (ELEMENT *) k->value; + add_extra_string_dup (owning_element, "spaces_before_argument", + e->text.text); + destroy_element (e); } } else @@ -659,11 +669,13 @@ static void isolate_last_space_internal (ELEMENT *current) { ELEMENT *last_elt; + char *text; + int text_len; last_elt = last_contents_child (current); - char *text = element_text (last_elt); + text = element_text (last_elt); - int text_len = last_elt->text.end; + text_len = last_elt->text.end; /* If text all whitespace */ if (text[strspn (text, whitespace_chars)] == '\0') @@ -725,14 +737,17 @@ isolate_trailing_space (ELEMENT *current, enum element_type spaces_type) i--) trailing_spaces++; - new_spaces = new_element (spaces_type); - text_append_n (&new_spaces->text, - text + text_len - trailing_spaces, - trailing_spaces); - text[text_len - trailing_spaces] = '\0'; - last_elt->text.end -= trailing_spaces; - - add_to_element_contents (current, new_spaces); + if (trailing_spaces) + { + new_spaces = new_element (spaces_type); + text_append_n (&new_spaces->text, + text + text_len - trailing_spaces, + trailing_spaces); + text[text_len - trailing_spaces] = '\0'; + last_elt->text.end -= trailing_spaces; + + add_to_element_contents (current, new_spaces); + } } } @@ -760,7 +775,8 @@ isolate_last_space (ELEMENT *current) text = element_text (last_elt); if (!text || !*text || (last_elt->type && (!current->type - || current->type != ET_line_arg))) + || (current->type != ET_line_arg + && current->type != ET_block_line_arg)))) return; text_len = last_elt->text.end; @@ -775,11 +791,12 @@ isolate_last_space (ELEMENT *current) } -/* Add an "ET_empty_line_after_command" element containing the whitespace at - the beginning of the rest of the line. This element can be later changed to - a "ET_empty_spaces_after_command" element in 'abort_empty_line' if more - text follows on the line. Used after line commands or commands starting - a block. */ +/* Add an "ET_ignorable_spaces_after_command" element containing the + whitespace at the beginning of the rest of the line after skipspaces + commands, if COMMAND is 0. Otherwise add an + "ET_internal_spaces_after_command", container, after line commands + or commands starting a block, that will end up in COMMAND extra spaces + value. */ void start_empty_line_after_command (ELEMENT *current, char **line_inout, ELEMENT *command) @@ -789,22 +806,45 @@ start_empty_line_after_command (ELEMENT *current, char **line_inout, int len; len = strspn (line, whitespace_chars_except_newline); - e = new_element (ET_empty_line_after_command); + e = new_element (ET_ignorable_spaces_after_command); add_to_element_contents (current, e); text_append_n (&e->text, line, len); line += len; if (command) - add_extra_element (e, "command", command); + { + add_extra_element (e, "spaces_associated_command", command); + e->type = ET_internal_spaces_after_command; + } *line_inout = line; } -/* If the parent element takes a command as an argument, like - @itemize @bullet. */ +/* if kbd should be formatted as code */ int -command_with_command_as_argument (ELEMENT *current) +kbd_formatted_as_code (ELEMENT *current) +{ + if (global_kbdinputstyle == kbd_code) + { + return 1; + } + else if (global_kbdinputstyle == kbd_example) + { + if (in_preformatted_context_not_menu ()) + return 0; + else + return 1; + } + return 0; +} + + +/* If the container can hold a command as an argument, determined as + parent element taking a command as an argument, like + @itemize @bullet, and the command as argument being the only content. */ +int +parent_of_command_as_argument (ELEMENT *current) { return current->type == ET_block_line_arg && (current->parent->cmd == CM_itemize @@ -812,6 +852,24 @@ command_with_command_as_argument (ELEMENT *current) && (current->contents.number == 1); } +/* register a command like @bullet with @itemize, or @asis with @table */ +void +register_command_as_argument (ELEMENT *cmd_as_arg) +{ + debug ("FOR PARENT @%s command_as_argument @%s", + command_name(cmd_as_arg->parent->parent->cmd), + command_name(cmd_as_arg->cmd)); + if (!cmd_as_arg->type) + cmd_as_arg->type = ET_command_as_argument; + add_extra_element (cmd_as_arg->parent->parent, + "command_as_argument", cmd_as_arg); + if (cmd_as_arg->cmd == CM_kbd + && kbd_formatted_as_code(cmd_as_arg->parent->parent)) { + add_extra_integer (cmd_as_arg->parent->parent, + "command_as_argument_kbd_code", 1); + } +} + /* Check if line is "@end ..." for current command. If so, advance LINE. */ int is_end_current_command (ELEMENT *current, char **line, @@ -855,7 +913,7 @@ check_valid_nesting (ELEMENT *current, enum command_id cmd) /* Check whether outer command can contain cmd. Commands are classified according to what commands they can contain: - accents + plain text full text simple text full line @@ -865,8 +923,7 @@ check_valid_nesting (ELEMENT *current, enum command_id cmd) int ok = 0; /* Whether nesting is allowed. */ - /* Whether command is a "simple text" command. Use a variable - to avoid repeating a complex conditional. */ + /* Whether command is a "simple text" command */ int simple_text_command = 0; enum command_id outer = current->parent->cmd; @@ -875,27 +932,16 @@ check_valid_nesting (ELEMENT *current, enum command_id cmd) // much TODO here. - if ((outer_flags & CF_line - && (command_data(outer).data >= 0 - || (command_data(outer).data == LINE_line - && !(outer_flags & (CF_def | CF_sectioning))) - || command_data(outer).data == LINE_text) - && outer != CM_center - && outer != CM_exdent) - || ((outer_flags & CF_brace) - && !(outer_flags & CF_inline) - && command_data(outer).data > 0) - || outer == CM_shortcaption - || outer == CM_math - || (outer_flags & CF_index_entry_command) - || (outer_flags & CF_block - && !(outer_flags & CF_def) - && command_data(outer).data != BLOCK_raw - && command_data(outer).data != BLOCK_conditional)) + if (outer_flags & CF_contain_simple_text + /* not in CF_contain_simple_text since index entry flags are not set + in command_data.txt, and also index commands are dynamically added */ + || outer_flags & CF_index_entry_command) { simple_text_command = 1; } + /* first three conditions check if in the main contents of the commands + or in the arguments where there is checking of nesting */ if (outer_flags & CF_root && current->type != ET_line_arg) ok = 1; else if (outer_flags & CF_block @@ -905,12 +951,14 @@ check_valid_nesting (ELEMENT *current, enum command_id cmd) || outer == CM_itemx) && current->type != ET_line_arg) ok = 1; - else if (outer_flags & CF_accent) + else if (outer_flags & CF_contain_plain_text) { - if (cmd_flags & (CF_nobrace | CF_accent)) + if ((cmd_flags & CF_accent) + || (cmd_flags & CF_nobrace + && command_data(cmd).data == NOBRACE_symbol)) ok = 1; else if (cmd_flags & CF_brace - && command_data(cmd).data == 0) + && command_data(cmd).data == BRACE_noarg) ok = 1; /* glyph command */ if (cmd == CM_c || cmd == CM_comment) ok = 1; @@ -918,7 +966,9 @@ check_valid_nesting (ELEMENT *current, enum command_id cmd) else if (simple_text_command /* "full text commands" */ || (outer_flags & CF_brace) - && command_data(outer).data == BRACE_style + && (command_data(outer).data == BRACE_style_other + || command_data(outer).data == BRACE_style_code + || command_data(outer).data == BRACE_style_no_code) /* "full line commands" */ || outer == CM_center || outer == CM_exdent @@ -928,15 +978,20 @@ check_valid_nesting (ELEMENT *current, enum command_id cmd) || (!current->parent->cmd && current_context () == ct_def) /* "full line no refs commands" */ - || (outer_flags & (CF_sectioning | CF_def)) + || (outer_flags & (CF_sectioning_heading | CF_def)) || (!current->parent->cmd && current_context () == ct_def)) { /* Start by checking if the command is allowed inside a "full text command" - this is the most permissive. */ - if (cmd_flags & CF_nobrace) - ok = 1; + /* in the perl parser the checks are not dynamic as in this function, + a hash is used and modified when defining the definfoencose command */ + /* all the brace commands, not the definfoenclose commands, which + should be consistent with the perl parser */ if (cmd_flags & CF_brace && !(cmd_flags & CF_INFOENCLOSE)) ok = 1; + if (cmd_flags & CF_nobrace && command_data(cmd).data == NOBRACE_symbol) + ok = 1; + /* selected line commands */ else if (cmd == CM_c || cmd == CM_comment || cmd == CM_refill @@ -946,17 +1001,30 @@ check_valid_nesting (ELEMENT *current, enum command_id cmd) || cmd == CM_clear || cmd == CM_end) ok = 1; - else if (cmd_flags & CF_format_raw) + /* selected block commands */ + else if (cmd_flags & CF_block + && (command_data(cmd).data == BLOCK_format_raw + || command_data(cmd).data == BLOCK_conditional)) ok = 1; + /* not valid in these commands, only right in @float */ if (cmd == CM_caption || cmd == CM_shortcaption) ok = 0; - if (cmd_flags & CF_block - && command_data(cmd).data == BLOCK_conditional) - ok = 1; + + if (cmd_flags & CF_in_heading_spec) + { /* in heading commands can only appear in headings and style + brace commands */ + ok = 0; + if (outer_flags & CF_heading_spec + || (outer_flags & CF_brace + && (command_data(outer).data == BRACE_style_other + || command_data(outer).data == BRACE_style_code + || command_data(outer).data == BRACE_style_no_code))) + ok = 1; + } /* Now add more restrictions for "full line no refs" commands and "simple - text" commands. */ - if (outer_flags & (CF_sectioning | CF_def) + text" commands on valid brace commands. */ + if (outer_flags & (CF_sectioning_heading | CF_def) || (!current->parent->cmd && current_context () == ct_def) || simple_text_command) { @@ -968,7 +1036,7 @@ check_valid_nesting (ELEMENT *current, enum command_id cmd) ok = 0; } - /* Exceptions for "simple text commands" only. */ + /* Exceptions for "simple text commands" only for brace commands. */ if (simple_text_command) { if (cmd == CM_xref @@ -1007,7 +1075,10 @@ check_valid_nesting (ELEMENT *current, enum command_id cmd) } /* *LINEP is a pointer into the line being processed. It is advanced past any - bytes processed. Return 0 when we need to read a new line. */ + bytes processed. + Return STILL_MORE_TO_PROCESS when there is more to process on the line + GET_A_NEW_LINE when we need to read a new line + FINISHED_TOTALLY when @bye was found */ int process_remaining_on_line (ELEMENT **current_inout, char **line_inout) { @@ -1016,21 +1087,20 @@ process_remaining_on_line (ELEMENT **current_inout, char **line_inout) char *line_after_command; int retval = STILL_MORE_TO_PROCESS; enum command_id end_cmd; - char *p; enum command_id cmd = CM_NONE; + /* remains set only if command is unknown, otherwise cmd is used */ + char *command = 0; - /********* BLOCK_raw or (ignored) BLOCK_conditional ******************/ - /* If in raw block, or ignored conditional block. */ + /********* BLOCK_raw ******************/ if (command_flags(current) & CF_block - && (command_data(current->cmd).data == BLOCK_raw - || command_data(current->cmd).data == BLOCK_conditional)) + && (command_data(current->cmd).data == BLOCK_raw)) { + char *p = line; /* Check if we are using a macro within a macro. */ if (current->cmd == CM_macro || current->cmd == CM_rmacro) { enum command_id cmd = 0; - char *p = line; p += strspn (p, whitespace_chars); if (!strncmp (p, "@macro", strlen ("@macro"))) { @@ -1054,42 +1124,12 @@ process_remaining_on_line (ELEMENT **current_inout, char **line_inout) goto funexit; } } - - /* Else check for nested @ifset (so that @end ifset doesn't - end the outermost @ifset). */ - if (current->cmd == CM_ifclear || current->cmd == CM_ifset - || current->cmd == CM_ifcommanddefined - || current->cmd == CM_ifcommandnotdefined) - { - ELEMENT *e; - char *p = line; - p += strspn (p, whitespace_chars); - if (*p == '@' - && !strncmp (p + 1, command_name(current->cmd), - strlen (command_name(current->cmd)))) - { - line = p + 1; - p += strlen (command_name(current->cmd)); - e = new_element (ET_NONE); - e->cmd = current->cmd; - add_extra_string (e, "line", strdup (line)); - add_to_element_contents (current, e); - current = e; - retval = GET_A_NEW_LINE; - goto funexit; - } - } - /* Else check if line is "@end ..." for current command. */ - p = line; - if (is_end_current_command (current, &line, &end_cmd)) + if (is_end_current_command (current, &p, &end_cmd)) { - ELEMENT *last_child; - char *tmp = 0; + ELEMENT *e; - last_child = last_contents_child (current); - - if (strchr (whitespace_chars, *p)) + if (strchr (whitespace_chars, *line)) { ELEMENT *e; int n = strspn (line, whitespace_chars); @@ -1100,42 +1140,6 @@ process_remaining_on_line (ELEMENT **current_inout, char **line_inout) line_warn ("@end %s should only appear at the " "beginning of a line", command_name(end_cmd)); } - else if (last_child - && last_child->type == ET_raw - && current->cmd != CM_verbatim) - { - if (last_child->text.end > 0 - && last_child->text.text[last_child->text.end - 1] == '\n') - { - ELEMENT *lrn; - last_child->text.text[--last_child->text.end] = '\0'; - lrn = new_element (ET_last_raw_newline); - text_append (&lrn->text, "\n"); - add_to_element_contents (current, lrn); - } - } - - /* 'line' is now advanced past the "@end ...". Check if - there's anything after it. */ - p = line + strspn (line, whitespace_chars); - if (*p && *p != '@') - goto superfluous_arg; - if (*p) - { - p++; - tmp = read_command_name (&p); - if (tmp && (!strcmp (tmp, "c") || !strcmp (tmp, "comment"))) - { - } - else if (*p && p[strspn (p, whitespace_chars)]) - { -superfluous_arg: - line_warn ("superfluous argument to @end %s: %s", - command_name (current->cmd), line); - } - free (tmp); - } - /* For macros, define a new macro (unless we are in a nested macro definition). */ @@ -1157,14 +1161,14 @@ superfluous_arg: macro = lookup_macro (existing); if (macro) { - line_error_ext (1, ¤t->line_nr, + line_error_ext (1, ¤t->source_info, "macro `%s' previously defined", name); - line_error_ext (1, ¯o->element->line_nr, + line_error_ext (1, ¯o->element->source_info, "here is the previous definition of `%s'", name); } else if (!(existing & USER_COMMAND_BIT)) { - line_error_ext (1, ¤t->line_nr, + line_error_ext (1, ¤t->source_info, "redefining Texinfo language command: @%s", name); } @@ -1176,66 +1180,111 @@ superfluous_arg: } } - current = current->parent; - /* Check for conditionals. */ - if (command_data(end_cmd).flags & CF_block - && command_data(end_cmd).data == BLOCK_conditional) - { - /* Remove an ignored block. */ - ELEMENT *popped; - popped = pop_element_from_contents (current); - if (popped->cmd != end_cmd) - fatal ("command mismatch for ignored block"); - - /* Ignore until end of line */ - if (!strchr (line, '\n')) - { - line = new_line (); - debug ("IGNORE CLOSE LINE"); - } - destroy_element_and_children (popped); + debug ("CLOSED raw %s", command_name(end_cmd)); + /* start a new line for the @end line (without the first spaces on + the line that have already been put in a raw container). + This is normally done at the beginning of a line, but not here, + as we directly got the line. As the @end is processed just below, + an empty line will not appear in the output, but it is needed to + avoid a duplicate warning on @end not appearing at the beginning + of the line */ + e = new_element (ET_empty_line); + add_to_element_contents (current, e); + } + else /* save the line verbatim */ + { + ELEMENT *e; + e = new_element (ET_raw); + text_append (&e->text, line); + add_to_element_contents (current, e); - debug ("CLOSED conditional %s", command_name(end_cmd)); - retval = GET_A_NEW_LINE; - goto funexit; - } - else - { - ELEMENT *e; - int n; + retval = GET_A_NEW_LINE; + goto funexit; + } + } /********* BLOCK_raw *************/ + /********* (ignored) BLOCK_conditional ******************/ + else if (command_flags(current) & CF_block + && (command_data(current->cmd).data == BLOCK_conditional)) + { + char *p = line; - debug ("CLOSED raw %s", command_name(end_cmd)); - e = new_element (ET_empty_line_after_command); - n = strspn (line, whitespace_chars_except_newline); - text_append_n (&e->text, line, n); - line += n; + /* check for nested @ifset (so that @end ifset doesn't end the + the outermost @ifset). It is discarded when the outermost is.*/ + if (current->cmd == CM_ifclear || current->cmd == CM_ifset + || current->cmd == CM_ifcommanddefined + || current->cmd == CM_ifcommandnotdefined) + { + ELEMENT *e; + p += strspn (p, whitespace_chars); + if (*p == '@' + && !strncmp (p + 1, command_name(current->cmd), + strlen (command_name(current->cmd)))) + { + e = new_element (ET_NONE); + e->cmd = current->cmd; add_to_element_contents (current, e); + current = e; + retval = GET_A_NEW_LINE; + goto funexit; } } - else /* save the line verbatim */ + + /* Else check if line is "@end ..." for current command. */ + if (is_end_current_command (current, &line, &end_cmd)) { - ELEMENT *last = last_contents_child (current); - /* Append to existing element only if the text is all - whitespace. */ - if (last && last->type == ET_empty_line_after_command - && line[strspn (line, whitespace_chars)] == '\0' - && !strchr (last->text.text, '\n')) + char *tmp = 0; + ELEMENT *popped; + + /* check whitespaces at the beginning of the line */ + if (strchr (whitespace_chars, *p)) { - text_append (&last->text, line); + line_warn ("@end %s should only appear at the " + "beginning of a line", command_name(end_cmd)); } - else + + current = current->parent; + + /* Remove an ignored block. */ + popped = pop_element_from_contents (current); + if (popped->cmd != end_cmd) + fatal ("command mismatch for ignored block"); + + /* 'line' is now advanced past the "@end ...". Check if + there's anything after it. */ + p = line + strspn (line, whitespace_chars); + if (*p && *p != '@') + goto superfluous_arg; + if (*p) { - ELEMENT *e; - e = new_element (ET_raw); - text_append (&e->text, line); - add_to_element_contents (current, e); + p++; + tmp = read_command_name (&p); + if (tmp && (!strcmp (tmp, "c") || !strcmp (tmp, "comment"))) + { + } + else if (*p && p[strspn (p, whitespace_chars)]) + { +superfluous_arg: + line_warn ("superfluous argument to @end %s: %s", + command_name(end_cmd), line); + } + free (tmp); } - retval = GET_A_NEW_LINE; - goto funexit; + /* Ignore until end of line */ + if (!strchr (line, '\n')) + { + line = new_line (); + debug ("IGNORE CLOSE LINE"); + } + destroy_element_and_children (popped); + + debug ("CLOSED conditional %s", command_name(end_cmd)); } - } /********* BLOCK_raw or (ignored) BLOCK_conditional *************/ + /* anything remaining on the line and any other line is ignored here */ + retval = GET_A_NEW_LINE; + goto funexit; + } /********* (ignored) BLOCK_conditional *************/ /* Check if parent element is 'verb' */ else if (current->parent && current->parent->cmd == CM_verb) @@ -1294,6 +1343,42 @@ superfluous_arg: retval = GET_A_NEW_LINE; goto funexit; /* Get next line. */ } } /* CM_verb */ + else if (command_flags(current) & CF_block + && command_data(current->cmd).data == BLOCK_format_raw + && !format_expanded_p (command_name(current->cmd))) + { + ELEMENT *e; + enum command_id dummy; + char *line_dummy; + int n; + + e = new_element (ET_elided_block); + add_to_element_contents (current, e); + line_dummy = line; + while (!is_end_current_command (current, &line_dummy, + &dummy)) + { + line = new_line (); + if (!line) + { + line = ""; + break; + } + line_dummy = line; + } + + /* start a new line for the @end line, this is normally done + at the beginning of a line, but not here, as we directly + got the lines. */ + e = new_element (ET_empty_line); + add_to_element_contents (current, e); + + n = strspn (line, whitespace_chars_except_newline); + text_append_n (&e->text, line, n); + line += n; + /* It is important to let the processing continue from here, such that + the @end is catched and handled below, as the condition has not changed */ + } /* ignored raw format */ /* Skip empty lines. If we reach the end of input, continue in case there is an @include. */ @@ -1339,30 +1424,18 @@ superfluous_arg: } else { - char *command = read_command_name (&line_after_command); + command = read_command_name (&line_after_command); cmd = 0; if (command) { - ELEMENT *paragraph; - cmd = lookup_command (command); - if (!cmd) + /* known command */ + if (cmd) { - line_error ("unknown command `%s'", command); - debug ("COMMAND (UNKNOWN) %s", command); free (command); - - abort_empty_line (¤t, 0); - paragraph = begin_paragraph (current); - if (paragraph) - current = paragraph; - - line = line_after_command; - retval = STILL_MORE_TO_PROCESS; - goto funexit; } - free (command); + /* command holds the unknown command name if !cmd && command */ } else { @@ -1374,7 +1447,7 @@ superfluous_arg: cmd = command_data(cmd).data; } - /* Handle user-defined macros before anything else because their expansion + /* Handle user-defined macros before anything else because their expansion may lead to changes in the line. */ if (cmd && (command_data(cmd).flags & CF_MACRO)) { @@ -1384,112 +1457,188 @@ superfluous_arg: free (allocated_line); allocated_line = next_text (); line = allocated_line; + retval = STILL_MORE_TO_PROCESS; + goto funexit; } - - /* Cases that may "lead to command closing": brace commands that don't - need a brace: accent commands. - @definfoenclose. */ - /* This condition is only checked immediately after the command opening, - otherwise the current element is in the 'args' and not right in the - command container. */ - else if (command_flags(current) & CF_brace && *line != '{') + /* expand value if it actually expands and changes the line. It is + considered again together with other commands below for all the other cases + which may need a well formed tree, which is not needed nor available here, + and early value expansion may be needed to provide with an argument. */ + else if (cmd == CM_value) { - if (command_with_command_as_argument (current->parent)) - { - debug ("FOR PARENT @%s command_as_argument @%s", - command_name(current->parent->parent->cmd), - command_name(current->cmd)); - if (!current->type) - current->type = ET_command_as_argument; - add_extra_element (current->parent->parent, - "command_as_argument", current); - current = current->parent; - } - else if (command_flags(current) & CF_accent) + char *expanded_line = line_after_command; + if (conf.ignore_space_after_braced_command_name) + expanded_line += strspn (expanded_line, whitespace_chars); + if (*expanded_line == '{') { - if (strchr (whitespace_chars_except_newline, *line)) + char *flag; + + expanded_line++; + flag = read_flag_name (&expanded_line); + if (flag) { - if (isalpha (command_name(current->cmd)[0])) - /* e.g. @dotaccent */ + if (*expanded_line == '}') { - char *p; char *s; - KEY_PAIR *k; - p = line + strspn (line, whitespace_chars_except_newline); - k = lookup_extra (current, "spaces"); - if (!k) - { - asprintf (&s, "%.*s", (int) (p - line), line); - add_extra_string (current, "spaces", s); - } - else + char *value; + value = fetch_value (flag); + + if (value) { - asprintf (&s, "%s%.*s", - (char *) k->value, - (int) (p - line), p); - free (k->value); - k->value = (ELEMENT *) s; + expanded_line++; /* past '}' */ + input_push_text (strdup (expanded_line), current_source_info.macro); + input_push_text (strdup (value), current_source_info.macro); + + /* Move 'line' to end of string so next input to + be processed is taken from input stack. */ + line = expanded_line + strlen (expanded_line); + retval = STILL_MORE_TO_PROCESS; } - line = p; - } - else - { - line_warn ("accent command `@%s' must not be followed " - "by whitespace", command_name(current->cmd)); - current = current->parent; + free (flag); + if (value) + goto funexit; } } - else if (*line == '@') - { - line_error ("use braces to give a command as an argument " - "to @%s", command_name(current->cmd)); - current = current->parent; - } - else if (*line != '\0' && *line != '\n' && *line != '\r') - { - ELEMENT *e, *e2; - debug ("ACCENT"); - e = new_element (ET_following_arg); - add_to_element_args (current, e); - e2 = new_element (ET_NONE); - text_append_n (&e2->text, line, 1); - add_to_element_contents (e, e2); - - if (current->cmd == CM_dotless - && *line != 'i' && *line != 'j') - { - line_error ("@dotless expects `i' or `j' as argument, " - "not `%c'", *line); - } - if (isalpha (command_name(current->cmd)[0])) - e->type = ET_space_command_arg; - while (current->contents.number > 0) - destroy_element (pop_element_from_contents (current)); - line++; - current = current->parent; - } - else + } + } + + /* special case for @-command as argument of @itemize or @*table. + The normal case for those are to be identifier only, not a true command + with argument, so can be followed by anything. If followed by + braces, will be handled as a normal brace command. + + Need to be done as early as possible such that no other condition + prevail and lead to a missed command */ + if (command_flags(current) & CF_brace && *line != '{' + && parent_of_command_as_argument (current->parent)) + { + register_command_as_argument (current); + current = current->parent; + } + + /* command but before an opening brace, otherwise current + would be an argument type and not the command, and a new + @-command was found. This means that the current->cmd + argument (an opening brace, or a character after spaces for + accent commands) was not found and there is already a new command. + + It would have been nice to allow for comments, but there is no + container in the tree to put them when after command and before brace + or argument for accent commands. */ + + if (command_flags(current) & CF_brace && (cmd || command)) + { + line_error ("@%s expected braces", + command_name(current->cmd)); + current = current->parent; + } + + /* Handle unknown command. */ + if (!cmd && command) + { + ELEMENT *paragraph; + + line_error ("unknown command `%s'", command); + debug ("COMMAND (UNKNOWN) %s", command); + free (command); + abort_empty_line (¤t, 0); + paragraph = begin_paragraph (current); + if (paragraph) + current = paragraph; + + line = line_after_command; + retval = STILL_MORE_TO_PROCESS; + goto funexit; + } + + /* Brace commands not followed immediately by a brace + opening. In particular cases that may lead to "command closing" + or following character association with an @-command, for accent + commands */ + /* This condition can only happen immediately after the command opening, + otherwise the current element is in the 'args' and not right in the + command container. */ + if (command_flags(current) & CF_brace && *line != '{') + { + if (strchr (whitespace_chars, *line) + && ((command_flags(current) & CF_accent) + || conf.ignore_space_after_braced_command_name)) + { + char *p; char *s; + int whitespaces_len; + int additional_newline = 0; + KEY_PAIR *k; + whitespaces_len = strspn (line, whitespace_chars); + + for (int i = 0; i < whitespaces_len; i++) + { + if (*(line + i) == '\n') + { + line_warn ("command `@%s' must not be followed by new line", + command_name(current->cmd)); + additional_newline = 1; + break; + } + } + + k = lookup_extra (current, "spaces"); + if (!k) + { + p = line + whitespaces_len; + xasprintf (&s, "%.*s", (int) (p - line), line); + add_extra_string (current, "spaces", s); + line = p; + } + else + { + /* only ignore spaces and one newline, two newlines lead to + an empty line before the brace or argument which is incorrect. */ + char *previous_value = (char *) k->value; + if (additional_newline && strchr ("\n", *previous_value)) + { + line_error ("@%s expected braces", + command_name(current->cmd)); + current = current->parent; + } + else + { + p = line + whitespaces_len; + xasprintf (&s, "%s%.*s", + previous_value, + (int) (p - line), line); + free (k->value); + k->value = (ELEMENT *) s; + line = p; + } + } + } + /* special case for accent commands, use following character except @ + * as argument */ + else if ((command_flags(current) & CF_accent) + && *line != '\0' && *line != '@') + { + ELEMENT *e, *e2; + debug ("ACCENT"); + e = new_element (ET_following_arg); + add_to_element_args (current, e); + e2 = new_element (ET_NONE); + text_append_n (&e2->text, line, 1); + add_to_element_contents (e, e2); + + if (current->cmd == CM_dotless + && *line != 'i' && *line != 'j') { - debug ("STRANGE ACC"); - line_warn ("accent command `@%s' must not be followed by " - "new line", command_name(current->cmd)); - current = current->parent; + line_error ("@dotless expects `i' or `j' as argument, " + "not `%c'", *line); } - goto funexit; + while (current->contents.number > 0) + destroy_element (pop_element_from_contents (current)); + line++; + current = current->parent; } else { - if (conf.ignore_space_after_braced_command_name) - { - char *p; - p = line + strspn (line, whitespace_chars); - if (p != line) - { - line = p; - goto funexit; - } - } line_error ("@%s expected braces", - command_name(current->cmd)); + command_name(current->cmd)); current = current->parent; } } @@ -1505,12 +1654,13 @@ superfluous_arg: line = line_after_command; debug ("COMMAND %s", command_name(cmd)); - /* @value */ - if (cmd == CM_value) + /* @value not expanded (expansion is done above), and @txiinternalvalue */ + if ((cmd == CM_value) || (cmd == CM_txiinternalvalue)) { char *arg_start; char *flag; - line += strspn (line, whitespace_chars); + if (conf.ignore_space_after_braced_command_name) + line += strspn (line, whitespace_chars); if (*line != '{') goto value_invalid; @@ -1530,51 +1680,64 @@ superfluous_arg: { char *value; value_valid: - value = fetch_value (flag); - if (!value) + if (cmd == CM_value) { - /* Add element for unexpanded @value. - This is not necessarily an error - in - Texinfo::Report::gdt we deliberately pass - in undefined values. */ - ELEMENT *value_elt; - - line_warn ("undefined flag: %s", flag); - /* Note: In the Perl code, this warning is conditional on - in_gdt setting, but the only effect that this possibly has - is on speed, as these warnings would not be printed to the - user. */ + value = fetch_value (flag); + if (!value) + { + /* Add element for unexpanded @value. + This should be an error, but still leave a tree element + for the converters to handle */ + ELEMENT *value_elt; - abort_empty_line (¤t, NULL); - value_elt = new_element (ET_NONE); - value_elt->cmd = CM_value; - text_append (&value_elt->text, flag); + line_warn ("undefined flag: %s", flag); - /* In the Perl code, the name of the flag is stored in - the "type" field. We need to store in 'text' instead - and then output it as the type in - dump_perl.c / api.c. */ + abort_empty_line (¤t, NULL); + value_elt = new_element (ET_NONE); + value_elt->cmd = CM_value; + add_extra_string_dup (value_elt, "flag", flag); - add_to_element_contents (current, value_elt); + add_to_element_contents (current, value_elt); - line++; /* past '}' */ - retval = STILL_MORE_TO_PROCESS; + line++; /* past '}' */ + retval = STILL_MORE_TO_PROCESS; + } + /* expansion of value already done above + else + { + value is set + } + */ + free (flag); + goto funexit; } else - { + { /* CM_txiinternalvalue */ + ELEMENT *txiinternalvalue_elt, *txiinternalvalue_arg; + + abort_empty_line (¤t, NULL); + txiinternalvalue_elt = new_element (ET_NONE); + txiinternalvalue_elt->cmd = CM_txiinternalvalue; + + /* FIXME or ET_misc_arg? */ + txiinternalvalue_arg = new_element (ET_NONE); + + text_append (&txiinternalvalue_arg->text, flag); + add_to_element_args (txiinternalvalue_elt, txiinternalvalue_arg); + + add_to_element_contents (current, txiinternalvalue_elt); + line++; /* past '}' */ - input_push_text (strdup (line), line_nr.macro); - input_push_text (strdup (value), line_nr.macro); - line += strlen (line); retval = STILL_MORE_TO_PROCESS; + + free (flag); + goto funexit; } - free (flag); - goto funexit; } else { value_invalid: - line_error ("bad syntax for @value"); + line_error ("bad syntax for @%s", command_name(cmd)); retval = STILL_MORE_TO_PROCESS; goto funexit; } @@ -1591,7 +1754,7 @@ value_invalid: break; } if (!msg) - line_warn ("@%s is obsolete.", command_name(cmd)); + line_warn ("@%s is obsolete", command_name(cmd)); else line_warn ("@%s is obsolete; %s", command_name(cmd), msg); /* note: will have to translate msg if string translation with @@ -1633,7 +1796,12 @@ value_invalid: /* check command doesn't start a paragraph */ /* TODO store this in cmd->flags. */ - if (!(command_data(cmd).flags & (CF_line | CF_other | CF_block) + if (!((command_data(cmd).flags & (CF_line | CF_block)) + || (command_data(cmd).flags & CF_nobrace + && (command_data(cmd).data == NOBRACE_skipspace + /* FIXME NOBRACE_other should probably start a paragraph + except for refill */ + || command_data(cmd).data == NOBRACE_other)) || cmd == CM_titlefont || cmd == CM_caption || cmd == CM_shortcaption @@ -1652,7 +1820,7 @@ value_invalid: if (cmd) { - if (close_paragraph_command (cmd)) + if (command_data(cmd).flags & CF_close_paragraph) current = end_paragraph (current, 0, 0); if (close_preformatted_command (cmd)) current = end_preformatted (current, 0, 0); @@ -1663,16 +1831,33 @@ value_invalid: || cmd == CM_seealso || cmd == CM_subentry) && current->contents.number > 0 - && last_contents_child(current)->text.end > 0) + && last_contents_child(current)->text.end > 0 + /* it is important to check if in an index command, as otherwise + the internal space type is not processed and remains as is in + the final tree. */ + && (command_flags(current->parent) & CF_index_entry_command + || current->parent->cmd == CM_subentry)) { - isolate_trailing_space (current, ET_empty_spaces_before_argument); + if (cmd == CM_subentry) + { + isolate_trailing_space (current, ET_spaces_at_end); + } + else + /* an internal and temporary space type that is converted to + a normal space without type if followed by text or a + "spaces_at_end" if followed by spaces only when the + index or subentry command is done. */ + { + isolate_trailing_space (current, ET_internal_spaces_before_brace_in_index); + } } if (cmd == CM_item && item_line_parent (current)) cmd = CM_item_LINE; /* We could possibly have done this before check_valid_nesting. */ - if (command_data(cmd).flags & CF_other) + /* No-brace command */ + if (command_data(cmd).flags & CF_nobrace) { int status; current = handle_other_command (current, &line, cmd, &status); @@ -1708,26 +1893,6 @@ value_invalid: { current = handle_brace_command (current, &line, cmd); } - /* No-brace command */ - else if (command_data(cmd).flags & CF_nobrace) - { - ELEMENT *nobrace; - - nobrace = new_element (ET_NONE); - nobrace->cmd = cmd; - add_to_element_contents (current, nobrace); - - if (cmd == CM_BACKSLASH && current_context () != ct_math) - { - line_warn ("@\\ should only appear in math context"); - } - if (cmd == CM_NEWLINE) - { - current = end_line (current); - retval = GET_A_NEW_LINE; - goto funexit; - } - } } /* "Separator" character */ else if (*line != '\0' && strchr ("{}@,:\t.\f", *line)) @@ -1811,8 +1976,8 @@ check_line_directive (char *line) return 0; /* Check input is coming directly from a file. */ - if (!line_nr.file_name || !line_nr.file_name - || (line_nr.macro && *line_nr.macro)) + if (!current_source_info.file_name || !current_source_info.file_name + || (current_source_info.macro && *current_source_info.macro)) return 0; p += strspn (p, " \t"); @@ -1859,11 +2024,12 @@ check_line_directive (char *line) return 1; } -/* Pass in and return root of a "Texinfo tree". */ +/* Pass in and return root of a "Texinfo tree". Starting point for adding + to the tree is current_elt */ ELEMENT * -parse_texi (ELEMENT *root_elt) +parse_texi (ELEMENT *root_elt, ELEMENT *current_elt) { - ELEMENT *current = root_elt; + ELEMENT *current = current_elt; static char *allocated_line; char *line; @@ -1877,13 +2043,16 @@ parse_texi (ELEMENT *root_elt) debug_nonl ("NEW LINE %s", line); - /* If not in 'raw' or 'conditional' and parent isn't a 'verb', collect + /* If not in 'raw' or 'conditional' and parent isn't a 'verb', + and not an ignored raw format, collect leading whitespace and save as an "ET_empty_line" element. This element type can be changed in 'abort_empty_line' when more text is read. */ - if (!((command_flags(current) & CF_block) - && (command_data(current->cmd).data == BLOCK_raw - || command_data(current->cmd).data == BLOCK_conditional) + if (!(((command_flags(current) & CF_block) + && ((command_data(current->cmd).data == BLOCK_raw + || command_data(current->cmd).data == BLOCK_conditional) + || (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) { @@ -1897,7 +2066,7 @@ parse_texi (ELEMENT *root_elt) if (current->contents.number > 0 && last_contents_child(current)->type - == ET_empty_spaces_before_argument) + == ET_internal_spaces_before_argument) { /* Remove this element and update 'extra' values. */ abort_empty_line (¤t, 0); @@ -1921,7 +2090,10 @@ parse_texi (ELEMENT *root_elt) if (status == FINISHED_TOTALLY) goto finished_totally; if (!line) - break; + { + current = end_line (current); + break; + } } } finished_totally: diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/parser.h b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/parser.h index 9cc2f240b4..7303a53357 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/parser.h +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/parser.h @@ -35,7 +35,6 @@ typedef struct GLOBAL_INFO { char *input_encoding_name; char *input_perl_encoding; int sections_level; - int novalidate; ELEMENT dircategory_direntry; /* an array of elements */ /* Elements that should be unique. */ @@ -63,6 +62,13 @@ typedef struct GLOBAL_INFO { ELEMENT *evenfootingmarks; ELEMENT *oddfootingmarks; ELEMENT *shorttitlepage; + ELEMENT *novalidate; + ELEMENT *afourpaper; + ELEMENT *afourlatex; + ELEMENT *afourwide; + ELEMENT *afivepaper; + ELEMENT *bsixpaper; + ELEMENT *smallbook; /* Arrays of elements */ ELEMENT footnotes; @@ -88,22 +94,26 @@ typedef struct GLOBAL_INFO { ELEMENT frenchspacing; ELEMENT headings; ELEMENT kbdinputstyle; + ELEMENT microtype; ELEMENT paragraphindent; ELEMENT shortcontents; ELEMENT urefbreakstyle; ELEMENT xrefautomaticsectiontitle; + + /* Ignored characters for index sort key */ + IGNORED_CHARS ignored_chars; } GLOBAL_INFO; /* In close.c */ void close_command_cleanup (ELEMENT *current); -ELEMENT *close_commands (ELEMENT *current, enum command_id closed_command, +ELEMENT *close_commands (ELEMENT *current, enum command_id closed_block_command, ELEMENT **closed_element, enum command_id); ELEMENT *close_all_style_commands (ELEMENT *current, - enum command_id closed_command, + enum command_id closed_block_command, enum command_id interrupting_command); ELEMENT *close_current (ELEMENT *current, - enum command_id closed_command, + enum command_id closed_block_command, enum command_id interrupting_command); /* In end_line.c */ @@ -132,20 +142,22 @@ ELEMENT *handle_separator (ELEMENT *current, char separator, char **line_inout); /* In parser.c */ -ELEMENT *parse_texi (ELEMENT *root_elt); +ELEMENT *parse_texi (ELEMENT *root_elt, ELEMENT *current_elt); void push_conditional_stack (enum command_id cond); enum command_id pop_conditional_stack (void); extern size_t conditional_number; -ELEMENT *parse_texi_file (char *filename); +ELEMENT *parse_texi_document (void); int abort_empty_line (ELEMENT **current_inout, char *additional); ELEMENT *end_paragraph (ELEMENT *current, - enum command_id closed_command, + enum command_id closed_block_command, enum command_id interrupting_command); void isolate_last_space (ELEMENT *current); -int command_with_command_as_argument (ELEMENT *current); +int kbd_formatted_as_code (ELEMENT *current); +int parent_of_command_as_argument (ELEMENT *current); +void register_command_as_argument (ELEMENT *cmd_as_arg); ELEMENT *begin_preformatted (ELEMENT *current); ELEMENT *end_preformatted (ELEMENT *current, - enum command_id closed_command, + enum command_id closed_block_command, enum command_id interrupting_command); char *read_command_name (char **ptr); char *read_flag_name (char **ptr); @@ -157,8 +169,10 @@ int format_expanded_p (char *format); int is_end_current_command (ELEMENT *current, char **line, enum command_id *end_cmd); void set_documentlanguage (char *); -void set_novalidate (int value); +void set_documentlanguage_override (char *value); +void set_accept_internalvalue (void); char *element_type_name (ELEMENT *e); +int check_space_element (ELEMENT *e); /* Return values */ #define GET_A_NEW_LINE 0 @@ -176,6 +190,8 @@ extern ELEMENT *current_part; extern GLOBAL_INFO global_info; extern char *global_clickstyle; extern char *global_documentlanguage; +extern int global_documentlanguage_fixed; +extern int global_accept_internalvalue; enum kbd_enum {kbd_none, kbd_code, kbd_example, kbd_distinct }; extern enum kbd_enum global_kbdinputstyle; @@ -185,6 +201,8 @@ void wipe_global_info (void); extern COUNTER count_remaining_args, count_items, count_cells; +ELEMENT *setup_document_root_and_before_node_section (void); + /* In multitable.c */ ELEMENT *item_line_parent (ELEMENT *current); ELEMENT *item_multitable_parent (ELEMENT *current); diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/separator.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/separator.c index b509de3d6a..dd1c49b60a 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/separator.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/separator.c @@ -37,7 +37,7 @@ handle_open_brace (ELEMENT *current, char **line_inout) command = current->cmd; counter_push (&count_remaining_args, current, - command_data(current->cmd).data); + command_data(current->cmd).args_number); counter_dec (&count_remaining_args); arg = new_element (ET_NONE); @@ -105,16 +105,16 @@ handle_open_brace (ELEMENT *current, char **line_inout) switch (command) { case CM_footnote: - push_context (ct_footnote); + push_context (ct_brace_command, command); break; case CM_caption: - push_context (ct_caption); + push_context (ct_brace_command, command); break; case CM_shortcaption: - push_context (ct_shortcaption); + push_context (ct_brace_command, command); break; case CM_math: - push_context (ct_math); + push_context (ct_math, command); break; default: fatal ("no context for command"); @@ -124,10 +124,10 @@ handle_open_brace (ELEMENT *current, char **line_inout) ELEMENT *e; int n; n = strspn (line, whitespace_chars_except_newline); - e = new_element (ET_empty_spaces_before_argument); + e = new_element (ET_internal_spaces_before_argument); text_append_n (&e->text, line, n); add_to_element_contents (current, e); - add_extra_element (e, "command", current->parent); + add_extra_element (e, "spaces_associated_command", current->parent); line += n; } current->type = ET_brace_command_context; @@ -136,19 +136,19 @@ handle_open_brace (ELEMENT *current, char **line_inout) { current->type = ET_brace_command_arg; - /* Commands which are said to take a positive number of arguments - disregard leading and trailing whitespace. */ - if (command_data(command).data > 0) + /* Commands that disregard leading whitespace. */ + if (command_data(command).data == BRACE_arguments + || command_data(command).data == BRACE_inline) { ELEMENT *e; - e = new_element (ET_empty_spaces_before_argument); + e = new_element (ET_internal_spaces_before_argument); /* See comment in parser.c:merge_text */ text_append (&e->text, ""); add_to_element_contents (current, e); - add_extra_element (e, "command", current); + add_extra_element (e, "spaces_associated_command", current); if (command == CM_inlineraw) - push_context (ct_inlineraw); + push_context (ct_inlineraw, command); } } debug ("OPENED"); @@ -164,13 +164,13 @@ handle_open_brace (ELEMENT *current, char **line_inout) /* We need the line number here in case @ protects the end of the line. */ if (current->parent->parent->type == ET_def_line) - current->line_nr = line_nr; + current->source_info = current_source_info; - e = new_element (ET_empty_spaces_before_argument); + e = new_element (ET_internal_spaces_before_argument); text_append (&e->text, ""); /* See comment in parser.c:merge_text */ add_to_element_contents (current, e); debug ("BRACKETED in def/multitable"); - add_extra_element (e, "command", current); + add_extra_element (e, "spaces_associated_command", current); } else if (current->type == ET_rawpreformatted) { @@ -183,7 +183,7 @@ handle_open_brace (ELEMENT *current, char **line_inout) || current_context() == ct_inlineraw) { ELEMENT *b = new_element (ET_bracketed); - b->line_nr = line_nr; + b->source_info = current_source_info; add_to_element_contents (current, b); current = b; debug ("BRACKETED in math"); @@ -193,7 +193,7 @@ handle_open_brace (ELEMENT *current, char **line_inout) line_error ("misplaced {"); if (current->contents.number > 0 && last_contents_child(current)->type - == ET_empty_spaces_before_argument) + == ET_internal_spaces_before_argument) { /* FIXME: Is this right? */ remove_from_contents (current, 0); @@ -207,9 +207,6 @@ handle_open_brace (ELEMENT *current, char **line_inout) /* Return 1 if an element is all whitespace. Note that this function isn't completely reliable because it doesn't look deep into the element tree. - In the perl code it calls - Texinfo::Convert::NodeNameNormalization::normalize_node, - and checks that the result isn't all hyphens. */ int check_empty_expansion (ELEMENT *e) @@ -218,19 +215,7 @@ check_empty_expansion (ELEMENT *e) for (i = 0; i < e->contents.number; i++) { ELEMENT *f = e->contents.list[i]; - if (!( - f->cmd == CM_SPACE - || f->cmd == CM_TAB - || f->cmd == CM_NEWLINE - || f->cmd == CM_c - || f->cmd == CM_comment - || f->cmd == CM_COLON - || f->type == ET_empty_spaces_before_argument - || f->type == ET_spaces_at_end - || (!f->cmd && !f->type && f->text.end == 0) - || (f->text.end > 0 - && !*(f->text.text + strspn (f->text.text, whitespace_chars))) - )) + if (!check_space_element(f)) { return 0; } @@ -256,15 +241,18 @@ handle_close_brace (ELEMENT *current, char **line_inout) enum command_id closed_command; if (command_data(current->parent->cmd).data == BRACE_context) { - (void) pop_context (); - /* The Perl code here checks that the popped context and the - parent command match as strings. */ + if (current->parent->cmd == CM_math) + { + if (pop_context () != ct_math) + fatal ("math context expected"); + } + else if (pop_context () != ct_brace_command) + fatal ("context brace command context expected"); } - else if (command_data(current->parent->cmd).data > 0) + /* determine if trailing spaces are ignored */ + else if (command_data(current->parent->cmd).data == BRACE_arguments) { - /* @inline* always have end spaces considered as normal text */ - if (!(command_flags(current->parent) & CF_inline)) - isolate_last_space (current); + isolate_last_space (current); } closed_command = current->parent->cmd; @@ -272,14 +260,14 @@ handle_close_brace (ELEMENT *current, char **line_inout) counter_pop (&count_remaining_args); if (current->contents.number > 0 - && command_data(closed_command).data == 0) + && command_data(closed_command).data == BRACE_noarg) line_warn ("command @%s does not accept arguments", command_name(closed_command)); if (closed_command == CM_anchor) { NODE_SPEC_EXTRA *parsed_anchor; - current->parent->line_nr = line_nr; + current->parent->source_info = current_source_info; parsed_anchor = parse_node_manual (current); if (check_node_label (parsed_anchor, CM_anchor)) { @@ -398,14 +386,14 @@ handle_close_brace (ELEMENT *current, char **line_inout) } } } - else if ((command_data(closed_command).flags & CF_inline) + else if ((command_data(closed_command).data == BRACE_inline) || closed_command == CM_abbr || closed_command == CM_acronym) { if (current->parent->cmd == CM_inlineraw) { if (ct_inlineraw != pop_context ()) - fatal ("expected inlineraw context"); + fatal ("inlineraw context expected"); } if (current->parent->args.number == 0 || current->parent->args.list[0]->contents.number == 0) @@ -459,14 +447,10 @@ handle_close_brace (ELEMENT *current, char **line_inout) } } - else if (command_with_command_as_argument (current->parent->parent) + else if (parent_of_command_as_argument (current->parent->parent) && current->contents.number == 0) { - debug ("FOR PARENT ... command_as_argument_braces ..."); - if (!current->parent->type) - current->parent->type = ET_command_as_argument; - add_extra_element (current->parent->parent->parent, - "command_as_argument", current->parent); + register_command_as_argument (current->parent); } else if (current->parent->cmd == CM_sortas || current->parent->cmd == CM_seeentry @@ -510,7 +494,7 @@ handle_close_brace (ELEMENT *current, char **line_inout) || current->parent->cmd == CM_seealso) { ELEMENT *e; - e = new_element (ET_empty_spaces_after_close_brace); + e = new_element (ET_spaces_after_close_brace); text_append (&e->text, ""); add_to_element_contents (current->parent->parent, e); } @@ -528,10 +512,7 @@ handle_close_brace (ELEMENT *current, char **line_inout) goto funexit; } /* context brace command (e.g. @footnote) when there is a paragraph inside */ - else if (current_context() == ct_footnote - || current_context() == ct_caption - || current_context() == ct_shortcaption - || current_context() == ct_math) + else if (current_context() == ct_brace_command) { current = end_paragraph (current, 0, 0); if (current->parent @@ -539,7 +520,8 @@ handle_close_brace (ELEMENT *current, char **line_inout) && (command_data(current->parent->cmd).data == BRACE_context)) { enum command_id closed_command; - (void) pop_context (); + if (pop_context () != ct_brace_command) + fatal ("context brace command context expected"); debug ("CLOSING(context command)"); closed_command = current->parent->cmd; counter_pop (&count_remaining_args); @@ -576,7 +558,7 @@ handle_comma (ELEMENT *current, char **line_inout) type = current->type; current = current->parent; - if (command_flags(current) & CF_inline) + if (command_data(current->cmd).data == BRACE_inline) { KEY_PAIR *k; int expandp = 0; @@ -729,10 +711,10 @@ inlinefmtifelse_done: new_arg = new_element (type); add_to_element_args (current, new_arg); current = new_arg; - e = new_element (ET_empty_spaces_before_argument); + e = new_element (ET_internal_spaces_before_argument); text_append (&e->text, ""); /* See comment in parser.c:merge_text */ add_to_element_contents (current, e); - add_extra_element (e, "command", current); + add_extra_element (e, "spaces_associated_command", current); funexit: *line_inout = line; diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/text.c b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/text.c index 224464f529..7427560c5f 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/text.c +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/text.c @@ -1,4 +1,4 @@ -/* Copyright 2014-2021 Free Software Foundation, Inc. +/* Copyright 2014-2022 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -31,8 +31,6 @@ text_alloc (TEXT *t, size_t len) t->space = t->end + len; if (t->space < 10) t->space = 10; - /* This makes a huge difference under Valgrind, is not noticable - otherwise. */ t->space *= 2; t->text = realloc (t->text, t->space); if (!t->text) @@ -47,7 +45,7 @@ text_printf (TEXT *t, char *format, ...) char *s; va_start (v, format); - vasprintf (&s, format, v); + xvasprintf (&s, format, v); text_append (t, s); free (s); va_end (v); diff --git a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/tree_types.h b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/tree_types.h index 3f9f78209f..66e84cf956 100644 --- a/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/tree_types.h +++ b/macros/texinfo/texinfo/tp/Texinfo/XS/parsetexi/tree_types.h @@ -52,11 +52,11 @@ typedef struct ELEMENT_LIST { size_t space; } ELEMENT_LIST; -typedef struct LINE_NR { +typedef struct SOURCE_INFO { int line_nr; char *file_name; char *macro; -} LINE_NR; +} SOURCE_INFO; typedef struct ELEMENT { enum command_id cmd; @@ -65,7 +65,7 @@ typedef struct ELEMENT { ELEMENT_LIST args; ELEMENT_LIST contents; struct ELEMENT *parent; - LINE_NR line_nr; + SOURCE_INFO source_info; KEY_PAIR *extra; size_t extra_number; @@ -77,6 +77,13 @@ typedef struct ELEMENT { everywhere; */ } ELEMENT; +typedef struct IGNORED_CHARS { + int backslash; + int hyphen; + int lessthan; + int atsign; +} IGNORED_CHARS; + typedef struct { char *index_name; char *index_prefix; @@ -90,6 +97,7 @@ typedef struct { int number; /* Index of entry in containing index, 1-based. */ ELEMENT *region; char *sortas; /* the sort key for the index */ + IGNORED_CHARS ignored_chars; } INDEX_ENTRY; typedef struct INDEX { |