[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[no subject]
From: |
Patrice Dumas |
Date: |
Fri, 27 Oct 2023 12:57:49 -0400 (EDT) |
branch: master
commit f275f01a7514cda32c804108a7b851997ec478cf
Author: Patrice Dumas <pertusus@free.fr>
AuthorDate: Fri Oct 27 18:57:48 2023 +0200
* tp/Texinfo/XS/Makefile.am (libtexinfo_la_SOURCES),
tp/Texinfo/XS/main/command_stack.c (COMMAND_STACK)
(reset_command_stack, push_command, pop_command, top_command)
(enum command_type_variety, enum monospace_context, COMMAND_OR_TYPE)
(COMMAND_OR_TYPE_STACK, push_command_or_type, pop_command_or_type)
(top_command_or_type, STRING_STACK, push_string_stack_string)
(pop_string_stack, top_string_stack, MONOSPACE_CONTEXT_STACK)
(push_monospace, push_style_no_code, pop_monospace_context)
(top_monospace_context), parsetexi/context_stack.c: move code related
to command stack out of to main/command_stack.c and add code there
related to other stacks.
* tp/Texinfo/Convert/Converter.pm (encode_converter_document),
tp/Texinfo/XS/main/get_perl_info.c (html_converter_initialize_sv):
pass code_types and pre_class_types to XS.
* tp/Texinfo/XS/convert/convert_html.c (HTML_COMMAND_STRUCT)
(additional_format_context_cmd, HTML_align_cmd, html_commands_data)
(register_format_context_command, register_pre_class_command)
(html_converter_initialize), tp/Texinfo/XS/main/utils.c
(small_block_associated_command), tp/Texinfo/XS/main/utils.h
(SMALL_BLOC_COMMANDS_LIST): setup informations on commands, flags,
preformatted class and format context strings.
* tp/Texinfo/XS/convert/convert_html.c (type_conversion, type_open),
tp/Texinfo/XS/main/call_perl_function.c (call_types_conversion)
(call_types_open): call of perl conversion type and open type
functions.
* tp/Texinfo/XS/convert/convert_html.c (push_html_formatting_context)
(top_html_formatting_context, pop_html_formatting_context)
(html_new_document_context, html_pop_document_context)
(top_document_context), tp/Texinfo/XS/main/utils.h
(HTML_FORMATTING_CONTEXT, HTML_FORMATTING_CONTEXT_STACK)
(HTML_DOCUMENT_CONTEXT, HTML_DOCUMENT_CONTEXT_STACK): functions to
manipulate document context and formatting context.
* tp/Texinfo/XS/convert/convert_html.c (convert_to_html_internal),
tp/Texinfo/XS/main/build_perl_info.c (build_html_formatting_context)
(build_html_document_context, build_html_formatting_state),
tp/Texinfo/XS/main/call_perl_function.c (call_types_conversion),
tp/Texinfo/XS/main/element_types.txt, tp/Texinfo/XS/main/utils.h
(CONVERTER): add setting of document and formatting context, call
types formatting functions, more types of args formatted. Set
modified_state if the state has been changed and needs to be
reexported before calling a perl function. Pass document and
formatting context to perl before calling perl functions.
---
ChangeLog | 50 +++
tp/Texinfo/Convert/Converter.pm | 3 +-
tp/Texinfo/XS/Makefile.am | 2 +
tp/Texinfo/XS/convert/convert_html.c | 646 ++++++++++++++++++++++++++++--
tp/Texinfo/XS/main/build_perl_info.c | 204 +++++++++-
tp/Texinfo/XS/main/build_perl_info.h | 1 +
tp/Texinfo/XS/main/call_perl_function.c | 119 ++++++
tp/Texinfo/XS/main/command_stack.c | 134 ++++++-
tp/Texinfo/XS/main/command_stack.h | 58 ++-
tp/Texinfo/XS/main/element_types.c | 3 +
tp/Texinfo/XS/main/element_types.h | 3 +
tp/Texinfo/XS/main/element_types.txt | 8 +
tp/Texinfo/XS/main/get_perl_info.c | 95 ++++-
tp/Texinfo/XS/main/translations.h | 8 +-
tp/Texinfo/XS/main/tree_perl_api.h | 5 +
tp/Texinfo/XS/main/utils.c | 7 +
tp/Texinfo/XS/main/utils.h | 60 ++-
tp/Texinfo/XS/parsetexi/api.c | 1 +
tp/Texinfo/XS/parsetexi/close.c | 1 +
tp/Texinfo/XS/parsetexi/context_stack.c | 51 +--
tp/Texinfo/XS/parsetexi/context_stack.h | 16 +-
tp/Texinfo/XS/parsetexi/end_line.c | 1 +
tp/Texinfo/XS/parsetexi/handle_commands.c | 1 +
tp/Texinfo/XS/parsetexi/indices.c | 1 +
tp/Texinfo/XS/parsetexi/parser.c | 1 +
tp/Texinfo/XS/parsetexi/separator.c | 1 +
26 files changed, 1378 insertions(+), 102 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 7afe0d0c36..cc3788a3d7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,53 @@
+2023-10-27 Patrice Dumas <pertusus@free.fr>
+
+ * tp/Texinfo/XS/Makefile.am (libtexinfo_la_SOURCES),
+ tp/Texinfo/XS/main/command_stack.c (COMMAND_STACK)
+ (reset_command_stack, push_command, pop_command, top_command)
+ (enum command_type_variety, enum monospace_context, COMMAND_OR_TYPE)
+ (COMMAND_OR_TYPE_STACK, push_command_or_type, pop_command_or_type)
+ (top_command_or_type, STRING_STACK, push_string_stack_string)
+ (pop_string_stack, top_string_stack, MONOSPACE_CONTEXT_STACK)
+ (push_monospace, push_style_no_code, pop_monospace_context)
+ (top_monospace_context), parsetexi/context_stack.c: move code related
+ to command stack out of to main/command_stack.c and add code there
+ related to other stacks.
+
+ * tp/Texinfo/Convert/Converter.pm (encode_converter_document),
+ tp/Texinfo/XS/main/get_perl_info.c (html_converter_initialize_sv):
+ pass code_types and pre_class_types to XS.
+
+ * tp/Texinfo/XS/convert/convert_html.c (HTML_COMMAND_STRUCT)
+ (additional_format_context_cmd, HTML_align_cmd, html_commands_data)
+ (register_format_context_command, register_pre_class_command)
+ (html_converter_initialize), tp/Texinfo/XS/main/utils.c
+ (small_block_associated_command), tp/Texinfo/XS/main/utils.h
+ (SMALL_BLOC_COMMANDS_LIST): setup informations on commands, flags,
+ preformatted class and format context strings.
+
+ * tp/Texinfo/XS/convert/convert_html.c (type_conversion, type_open),
+ tp/Texinfo/XS/main/call_perl_function.c (call_types_conversion)
+ (call_types_open): call of perl conversion type and open type
+ functions.
+
+ * tp/Texinfo/XS/convert/convert_html.c (push_html_formatting_context)
+ (top_html_formatting_context, pop_html_formatting_context)
+ (html_new_document_context, html_pop_document_context)
+ (top_document_context), tp/Texinfo/XS/main/utils.h
+ (HTML_FORMATTING_CONTEXT, HTML_FORMATTING_CONTEXT_STACK)
+ (HTML_DOCUMENT_CONTEXT, HTML_DOCUMENT_CONTEXT_STACK): functions to
+ manipulate document context and formatting context.
+
+ * tp/Texinfo/XS/convert/convert_html.c (convert_to_html_internal),
+ tp/Texinfo/XS/main/build_perl_info.c (build_html_formatting_context)
+ (build_html_document_context, build_html_formatting_state),
+ tp/Texinfo/XS/main/call_perl_function.c (call_types_conversion),
+ tp/Texinfo/XS/main/element_types.txt, tp/Texinfo/XS/main/utils.h
+ (CONVERTER): add setting of document and formatting context, call
+ types formatting functions, more types of args formatted. Set
+ modified_state if the state has been changed and needs to be
+ reexported before calling a perl function. Pass document and
+ formatting context to perl before calling perl functions.
+
2023-10-27 Patrice Dumas <pertusus@free.fr>
* tp/Texinfo/Convert/HTML.pm (import): load conversion overrides only
diff --git a/tp/Texinfo/Convert/Converter.pm b/tp/Texinfo/Convert/Converter.pm
index c518b37ffb..7991632f4f 100644
--- a/tp/Texinfo/Convert/Converter.pm
+++ b/tp/Texinfo/Convert/Converter.pm
@@ -443,7 +443,8 @@ sub encode_converter_document($)
'document_descriptor' => $self->{'document_descriptor'}};
foreach my $variable ('style_commands_formatting', 'formatting_function',
- 'types_open', 'types_conversion', 'commands_open', 'commands_conversion')
{
+ 'types_open', 'types_conversion', 'commands_open', 'commands_conversion',
+ 'code_types', 'pre_class_types') {
if ($self->{$variable}) {
$result->{$variable} = $self->{$variable};
}
diff --git a/tp/Texinfo/XS/Makefile.am b/tp/Texinfo/XS/Makefile.am
index d2f9e90a54..2dc36990ed 100644
--- a/tp/Texinfo/XS/Makefile.am
+++ b/tp/Texinfo/XS/Makefile.am
@@ -143,6 +143,8 @@ libtexinfo_la_SOURCES= \
main/manipulate_tree.h \
main/node_name_normalization.c \
main/node_name_normalization.h \
+ main/command_stack.c \
+ main/command_stack.h \
main/targets.c \
main/targets.h \
main/utils.c \
diff --git a/tp/Texinfo/XS/convert/convert_html.c
b/tp/Texinfo/XS/convert/convert_html.c
index 225ef383a0..b2d0e4876f 100644
--- a/tp/Texinfo/XS/convert/convert_html.c
+++ b/tp/Texinfo/XS/convert/convert_html.c
@@ -77,6 +77,21 @@ typedef struct ARGS_FORMATTED {
#define F_AFT_url 0x0080
#define F_AFT_raw 0x0100
+#define HF_composition_context 0x0001
+#define HF_format_context 0x0002
+#define HF_format_raw 0x0004
+#define HF_pre_class 0x0008
+#define HF_upper_case 0x0010
+#define HF_HTML_align 0x0020
+
+typedef struct HTML_COMMAND_STRUCT {
+ unsigned long flags;
+ char *pre_class;
+ char *format_context;
+} HTML_COMMAND_STRUCT;
+
+static HTML_COMMAND_STRUCT html_commands_data[BUILTIN_CMD_NUMBER];
+
/* in specification of args. Number max +1 for a trailing 0 */
#define MAX_COMMAND_ARGS_NR 6
@@ -118,6 +133,8 @@ typedef struct COMMAND_ARGS_SPECIFICATION {
static COMMAND_ARGS_SPECIFICATION command_args_flags[BUILTIN_CMD_NUMBER];
+
+
static void convert_to_html_internal (CONVERTER *self, ELEMENT *e,
TEXT *result, char *explanation);
@@ -803,6 +820,39 @@ prepare_special_units (CONVERTER *self, int
output_units_descriptor,
destroy_strings_list (do_special);
}
+static enum command_id additional_format_context_cmd[] = {
+ CM_tab, CM_item, CM_itemx, CM_headitem, 0
+ };
+
+static enum command_id HTML_align_cmd[] = {
+ CM_raggedright, CM_flushleft, CM_flushright, CM_center, 0
+};
+
+/* TODO free? It should be freed at exit? */
+void
+register_format_context_command (enum command_id cmd)
+{
+ char *context_str;
+
+ xasprintf (&context_str, "@%s", builtin_command_data[cmd].cmdname);
+
+ html_commands_data[cmd].format_context = context_str;
+ html_commands_data[cmd].flags |= HF_format_context;
+}
+
+void register_pre_class_command (enum command_id cmd, enum command_id main_cmd)
+{
+ char *pre_class_str;
+
+ if (main_cmd)
+ pre_class_str = builtin_command_data[main_cmd].cmdname;
+ else
+ pre_class_str = builtin_command_data[cmd].cmdname;
+
+ html_commands_data[cmd].pre_class = pre_class_str;
+ html_commands_data[cmd].flags |= HF_pre_class;
+}
+
/* most of the initialization is done by html_converter_initialize_sv
in get_perl_info, the initialization that sdo not require information
from perl is done here */
@@ -823,6 +873,49 @@ html_converter_initialize (CONVERTER *self)
memcpy (&command_args_flags[cmd].flags, &default_commands_args[i].flags,
max_args);
}
+
+ for (i = 0; small_block_associated_command[i][0]; i++)
+ {
+ enum command_id small_cmd = small_block_associated_command[i][0];
+ enum command_id cmd = small_block_associated_command[i][1];
+ register_pre_class_command (small_cmd, cmd);
+ }
+
+ for (i = 1; i < BUILTIN_CMD_NUMBER; i++)
+ {
+ if (builtin_command_data[i].flags & CF_block
+ || builtin_command_data[i].flags & CF_root)
+ register_format_context_command (i);
+
+ if (builtin_command_data[i].flags & CF_preformatted
+ || builtin_command_data[i].flags & CF_root)
+ html_commands_data[i].flags |= HF_composition_context;
+
+ if (builtin_command_data[i].flags & CF_block)
+ {
+ if (builtin_command_data[i].data == BLOCK_menu)
+ html_commands_data[i].flags |= HF_composition_context;
+ else if (builtin_command_data[i].data == BLOCK_format_raw)
+ html_commands_data[i].flags |= HF_format_raw;
+ }
+
+ if (builtin_command_data[i].flags & CF_preformatted)
+ {
+ if (!(html_commands_data[i].flags & HF_pre_class))
+ register_pre_class_command (i, 0);
+ }
+ }
+ register_pre_class_command (CM_verbatim, 0);
+ register_pre_class_command (CM_menu, 0);
+ for (i = 0; additional_format_context_cmd[i]; i++)
+ register_format_context_command (additional_format_context_cmd[i]);
+
+ for (i = 0; HTML_align_cmd[i]; i++)
+ html_commands_data[i].flags |= HF_HTML_align | HF_composition_context;
+
+ html_commands_data[CM_float].flags |= HF_composition_context;
+
+ html_commands_data[CM_sc].flags |= HF_upper_case;
}
void
@@ -843,6 +936,7 @@ html_initialize_output_state (CONVERTER *self)
= (HTML_TARGET_LIST *) malloc (sizeof (HTML_TARGET_LIST));
memset (self->html_special_targets[i], 0, sizeof (HTML_TARGET_LIST));
}
+
}
static HTML_TARGET *
@@ -2278,6 +2372,141 @@ html_convert_init (CONVERTER *self)
self->title_titlepage = title_titlepage;
}
+static char *
+type_conversion (CONVERTER *self, enum element_type type,
+ ELEMENT *element, char *content)
+{
+ /* TODO call a C function if status is FRS_status_default_set
+ maybe putting function references in an array */
+ if (self->types_conversion[type].status > 0)
+ return call_types_conversion (self, type, element, content);
+ return 0;
+}
+
+static char *
+type_open (CONVERTER *self, enum element_type type, ELEMENT *element)
+{
+ /* TODO call a C function if status is FRS_status_default_set
+ maybe putting function references in an array */
+ if (self->types_open[type].status > 0)
+ return call_types_open (self, type, element);
+ return 0;
+}
+
+
+static void
+push_html_formatting_context (HTML_FORMATTING_CONTEXT_STACK *stack,
+ char *context_name)
+{
+ if (stack->top >= stack->space)
+ {
+ stack->stack
+ = realloc (stack->stack,
+ (stack->space += 5) * sizeof (HTML_FORMATTING_CONTEXT));
+ }
+
+ memset (&stack->stack[stack->top], 0, sizeof (HTML_FORMATTING_CONTEXT));
+
+ stack->stack[stack->top].context_name = strdup (context_name);
+
+ stack->top++;
+}
+
+static HTML_FORMATTING_CONTEXT *
+top_html_formatting_context (HTML_FORMATTING_CONTEXT_STACK *stack)
+{
+ if (stack->top == 0)
+ fatal ("HTML formatting context stack empty for top");
+
+ return &stack->stack[stack->top - 1];
+}
+
+static void
+pop_html_formatting_context (HTML_FORMATTING_CONTEXT_STACK *stack)
+{
+ if (stack->top == 0)
+ fatal ("HTML formatting context stack empty");
+
+ free (stack->stack[stack->top - 1].context_name);
+ stack->top--;
+}
+
+static void
+html_new_document_context (CONVERTER *self,
+ char *context_name, int document_global_context,
+ enum command_id block_command)
+{
+ HTML_DOCUMENT_CONTEXT_STACK *stack = &self->html_document_context;
+ if (stack->top >= stack->space)
+ {
+ stack->stack
+ = realloc (stack->stack,
+ (stack->space += 5) * sizeof (HTML_DOCUMENT_CONTEXT));
+ }
+
+ memset (&stack->stack[stack->top], 0, sizeof (HTML_DOCUMENT_CONTEXT));
+ stack->stack[stack->top].context = strdup (context_name);
+ stack->stack[stack->top].document_global_context = document_global_context;
+
+ push_style_no_code (&stack->stack[stack->top].monospace_context);
+ push_command_or_type (&stack->stack[stack->top].composition_context,
+ 0, 0);
+ if (block_command)
+ push_command (&stack->stack[stack->top].block_commands, block_command);
+
+ if (document_global_context)
+ {
+ self->document_global_context++;
+ self->modified_state++;
+ }
+
+ push_html_formatting_context (&stack->stack[stack->top].formatting_context,
+ context_name);
+
+ stack->top++;
+}
+
+static void
+html_pop_document_context (CONVERTER *self)
+{
+ HTML_DOCUMENT_CONTEXT_STACK *stack = &self->html_document_context;
+ HTML_DOCUMENT_CONTEXT *document_ctx;
+
+ if (stack->top == 0)
+ fatal ("HTML document context stack empty for pop");
+
+ document_ctx = &stack->stack[stack->top -1];
+
+ free (document_ctx->context);
+ free (document_ctx->monospace_context.stack);
+ free (document_ctx->composition_context.stack);
+ if (document_ctx->block_commands.top > 0)
+ pop_command (&document_ctx->block_commands);
+ free (document_ctx->block_commands.stack);
+ pop_html_formatting_context (&document_ctx->formatting_context);
+ free (document_ctx->formatting_context.stack);
+
+ if (document_ctx->document_global_context)
+ {
+ self->document_global_context--;
+ self->modified_state++;
+ }
+
+ stack->top--;
+}
+
+static HTML_DOCUMENT_CONTEXT *
+top_document_context (CONVERTER *self)
+{
+ HTML_DOCUMENT_CONTEXT_STACK *stack = &self->html_document_context;
+
+ if (stack->top == 0)
+ fatal ("HTML document context stack empty for top");
+
+ return &stack->stack[stack->top - 1];
+}
+
+
#define ADD(x) text_append (result, x)
/* EXPLANATION is used for debugging */
@@ -2336,19 +2565,47 @@ convert_to_html_internal (CONVERTER *self, ELEMENT
*element,
{
fprintf (stderr, "IGNORED %s\n", command_type.text);
}
+ return;
}
/* Process text */
if (element->text.space > 0)
{
- char *result = "";
+ TEXT text_result;
+ text_init (&text_result);
+ text_append (&text_result, "");
+ /* already converted to html, keep it as is, assume it cannot be NULL */
+ if (element->type == ET__converted)
+ text_append (&text_result, element->text.text);
+ else if (element->type == ET_untranslated)
+ {
+ char *translation_context
+ = lookup_extra_string (element, "translation_context");
+ ELEMENT *translated = gdt_tree (element->text.text, self->document,
+ self->conf, 0, translation_context, 0);
+
+ convert_to_html_internal (self, translated, &text_result,
+ "translated TEXT");
+ }
+ else
+ {
+ char *result = type_conversion (self, element->type, element,
+ element->text.text);
+ if (result)
+ {
+ text_append (&text_result, result);
+ free (result);
+ }
+ }
if (self->conf->DEBUG > 0)
{
- fprintf (stderr, "DO TEXT => `%s'\n", result);
+ fprintf (stderr, "DO TEXT => `%s'\n", text_result.text);
}
+ ADD(text_result.text);
+ free (text_result.text);
return;
}
@@ -2360,7 +2617,10 @@ convert_to_html_internal (CONVERTER *self, ELEMENT
*element,
enum command_id data_cmd = element_builtin_data_cmd (element);
if (builtin_command_data[data_cmd].flags & CF_root)
- self->current_root_command = element;
+ {
+ self->current_root_command = element;
+ self->modified_state++;
+ }
if (self->commands_conversion[cmd].status)
{
@@ -2368,7 +2628,104 @@ convert_to_html_internal (CONVERTER *self, ELEMENT
*element,
ARGS_FORMATTED *args_formatted = 0;
TEXT content_formatted;
- /* */
+ HTML_DOCUMENT_CONTEXT *top_document_ctx;
+ HTML_FORMATTING_CONTEXT *top_formating_ctx;
+
+ if (builtin_command_data[data_cmd].flags & CF_brace
+ && builtin_command_data[data_cmd].data == BRACE_context)
+ {
+ html_new_document_context (self,
+ builtin_command_data[data_cmd].cmdname, 0, 0);
+ self->modified_state++;
+
+ }
+ top_document_ctx = top_document_context (self);
+
+ if (html_commands_data[data_cmd].flags & HF_format_context)
+ {
+ push_html_formatting_context (
+ &top_document_ctx->formatting_context,
+ html_commands_data[cmd].format_context);
+ self->modified_state++;
+ }
+
+ top_formating_ctx
+ = top_html_formatting_context
(&top_document_ctx->formatting_context);
+
+ if (builtin_command_data[data_cmd].flags & CF_block)
+ {
+ push_command (&top_document_ctx->block_commands, data_cmd);
+ self->modified_state++;
+ }
+
+ if (html_commands_data[data_cmd].flags & HF_composition_context)
+ {
+ push_command_or_type (&top_document_ctx->composition_context,
+ cmd, 0);
+ self->modified_state++;
+ }
+
+ if (html_commands_data[data_cmd].flags & HF_pre_class)
+ {
+ push_string_stack_string
(&top_document_ctx->preformatted_classes,
+
html_commands_data[data_cmd].pre_class);
+ self->modified_state++;
+ }
+
+ if (html_commands_data[data_cmd].flags & HF_format_raw)
+ {
+ top_document_ctx->raw_ctx++;
+ self->modified_state++;
+ }
+ else if (data_cmd == CM_verbatim)
+ {
+ top_document_ctx->verbatim_ctx++;
+ self->modified_state++;
+ }
+
+ if (builtin_command_data[data_cmd].other_flags & CF_brace_code
+ || builtin_command_data[data_cmd].flags & CF_preformatted_code)
+ {
+ push_monospace (&top_document_ctx->monospace_context);
+ self->modified_state++;
+ }
+ else if (builtin_command_data[data_cmd].flags & CF_brace
+ && builtin_command_data[data_cmd].data ==
BRACE_style_no_code)
+ {
+ push_style_no_code (&top_document_ctx->monospace_context);
+ self->modified_state++;
+ }
+ else if (html_commands_data[data_cmd].flags & HF_upper_case)
+ {
+ top_formating_ctx->upper_case_ctx++;
+ self->modified_state++;
+ }
+ else if (builtin_command_data[data_cmd].flags & CF_math)
+ {
+ top_document_ctx->math_ctx++;
+ self->modified_state++;
+ /*
+ $convert_to_latex = 1 if ($self->get_conf('CONVERT_TO_LATEX_IN_MATH'));
+ */
+ }
+ if (cmd == CM_verb)
+ {
+ top_formating_ctx->space_protected++;
+ self->modified_state++;
+ }
+ else if (cmd == CM_w)
+ {
+ top_formating_ctx->no_break++;
+ self->modified_state++;
+ }
+
+ /*
+ my $result = '';
+ if (defined($self->{'commands_open'}->{$command_name})) {
+ $result .= &{$self->{'commands_open'}->{$command_name}}($self,
+ $command_name, $element);
+ }
+ */
if (element->contents.number > 0)
{
@@ -2376,7 +2733,13 @@ convert_to_html_internal (CONVERTER *self, ELEMENT
*element,
if (convert_to_latex)
{
- /* */
+ /*
+ $content_formatted
+ = Texinfo::Convert::LaTeX::convert_to_latex_math(undef,
+ {'contents' => $element->{'contents'}},
+ $self->{'options_latex_math'});
+
+ */
}
else
{
@@ -2471,23 +2834,193 @@ convert_to_html_internal (CONVERTER *self, ELEMENT
*element,
text_reset (&formatted_arg);
xasprintf (&explanation, "%s A[%d]monospace",
command_type.text, arg_idx);
- /*
- push @{$self->{'document_context'}->[-1]->{'monospace'}}, 1;
- convert_to_html_internal ...
- pop @{$self->{'document_context'}->[-1]->{'monospace'}};
- */
+ push_monospace
(&top_document_ctx->monospace_context);
+ self->modified_state++;
+
convert_to_html_internal (self, arg, &formatted_arg,
explanation);
+ pop_monospace_context
+ (&top_document_ctx->monospace_context);
+ self->modified_state++;
free (explanation);
arg_formatted->formatted[AFT_type_monospace]
= strdup (formatted_arg.text);
}
+ if (arg_flags & F_AFT_string)
+ {
+ HTML_DOCUMENT_CONTEXT *string_document_ctx;
+ text_reset (&formatted_arg);
+ html_new_document_context (self, command_type.text,
+ 0, 0);
+ string_document_ctx = top_document_context (self);
+ string_document_ctx->string_ctx++;
+ self->modified_state++;
+ xasprintf (&explanation, "%s A[%d]string",
+ command_type.text, arg_idx);
+ convert_to_html_internal (self, arg, &formatted_arg,
+ explanation);
+
+ free (explanation);
+ html_pop_document_context (self);
+ self->modified_state++;
+ arg_formatted->formatted[AFT_type_string]
+ = strdup (formatted_arg.text);
+ }
+ if (arg_flags & F_AFT_monospacestring)
+ {
+ HTML_DOCUMENT_CONTEXT *string_document_ctx;
+ text_reset (&formatted_arg);
+ html_new_document_context (self, command_type.text,
+ 0, 0);
+ string_document_ctx = top_document_context (self);
+ string_document_ctx->string_ctx++;
+ push_monospace
(&string_document_ctx->monospace_context);
+ self->modified_state++;
+ xasprintf (&explanation, "%s A[%d]monospacestring",
+ command_type.text, arg_idx);
+ convert_to_html_internal (self, arg, &formatted_arg,
+ explanation);
+
+ free (explanation);
+ pop_monospace_context
+ (&string_document_ctx->monospace_context);
+ html_pop_document_context (self);
+ self->modified_state++;
+ arg_formatted->formatted[AFT_type_monospacestring]
+ = strdup (formatted_arg.text);
+ }
+ if (arg_flags & F_AFT_monospacetext)
+ {
+ /*
+ $arg_formatted->{$arg_type}
+ = Texinfo::Convert::Text::convert_to_text($arg,
+ {'code' => 1,
+
Texinfo::Convert::Text::copy_options_for_convert_text($self)});
+ */
+ }
+ if (arg_flags & F_AFT_filenametext)
+ {
+ /*
+ # Always use encoded characters for file names
+ $arg_formatted->{$arg_type}
+ = Texinfo::Convert::Text::convert_to_text($arg,
+ {'code' => 1,
+ Texinfo::Convert::Text::copy_options_for_convert_text($self,
1)});
+ */
+ }
+ if (arg_flags & F_AFT_filenametext)
+ {
+ /*
+ # set the encoding to UTF-8 to always have a string that is
suitable
+ # for percent encoding.
+ my $text_conversion_options = {'code' => 1,
+ Texinfo::Convert::Text::copy_options_for_convert_text($self,
1)};
+ $text_conversion_options->{'enabled_encoding'} = 'utf-8';
+ $arg_formatted->{$arg_type}
+ = Texinfo::Convert::Text::convert_to_text($arg,
+ $text_conversion_options);
+ */
+ }
+ if (arg_flags & F_AFT_raw)
+ {
+ top_document_ctx->raw_ctx++;
+ self->modified_state++;
+ xasprintf (&explanation, "%s A[%d]raw",
+ command_type.text, arg_idx);
+ convert_to_html_internal (self, arg, &formatted_arg,
+ explanation);
+
+ free (explanation);
+ top_document_ctx->raw_ctx--;
+ self->modified_state++;
+ arg_formatted->formatted[AFT_type_raw]
+ = strdup (formatted_arg.text);
+ }
}
free (formatted_arg.text);
}
}
- /* */
+
+ if (html_commands_data[data_cmd].flags & HF_composition_context)
+ {
+ pop_command_or_type (&top_document_ctx->composition_context);
+ self->modified_state++;
+ }
+
+ if (html_commands_data[data_cmd].flags & HF_pre_class)
+ {
+ pop_string_stack (&top_document_ctx->preformatted_classes);
+ self->modified_state++;
+ }
+
+ if (cmd == CM_verb)
+ {
+ top_formating_ctx->space_protected--;
+ self->modified_state++;
+ }
+ else if (cmd == CM_w)
+ {
+ top_formating_ctx->no_break--;
+ self->modified_state++;
+ }
+
+ if (builtin_command_data[data_cmd].flags & CF_preformatted_code
+ || (builtin_command_data[data_cmd].flags & CF_brace
+ && builtin_command_data[data_cmd].data ==
BRACE_style_no_code)
+ || builtin_command_data[data_cmd].other_flags & CF_brace_code)
+ {
+ pop_monospace_context (&top_document_ctx->monospace_context);
+ self->modified_state++;
+ }
+ else if (html_commands_data[data_cmd].flags & HF_upper_case)
+ {
+ top_formating_ctx->upper_case_ctx--;
+ self->modified_state++;
+ }
+
+ else if (builtin_command_data[data_cmd].flags & CF_math)
+ {
+ top_document_ctx->math_ctx--;
+ self->modified_state++;
+ }
+
+ if (html_commands_data[data_cmd].flags & HF_format_raw)
+ {
+ top_document_ctx->raw_ctx--;
+ self->modified_state++;
+ }
+ else if (data_cmd == CM_verbatim)
+ {
+ top_document_ctx->verbatim_ctx--;
+ self->modified_state++;
+ }
+
+ if (builtin_command_data[data_cmd].flags & CF_block)
+ {
+ pop_command (&top_document_ctx->block_commands);
+ self->modified_state++;
+ }
+
+ if (html_commands_data[data_cmd].flags & HF_format_context)
+ {
+ pop_html_formatting_context (
+ &top_document_ctx->formatting_context);
+ self->modified_state++;
+ }
+
+ if (builtin_command_data[data_cmd].flags & CF_brace
+ && builtin_command_data[data_cmd].data == BRACE_context)
+ {
+ html_pop_document_context (self);
+ self->modified_state++;
+ }
+
+ if (element->cmd == CM_node)
+ {
+ self->current_node = element;
+ self->modified_state++;
+ }
/* args are formatted, now format the command itself */
if (self->commands_conversion[cmd].status)
@@ -2514,22 +3047,66 @@ convert_to_html_internal (CONVERTER *self, ELEMENT
*element,
}
if (builtin_command_data[data_cmd].flags & CF_root)
- self->current_root_command = 0;
+ {
+ self->current_root_command = 0;
+ self->modified_state++;
+ }
}
else if (element->type)
{
- char *type_name = element_type_names[element->type];
+ char *open_result;
+ enum element_type type = element->type;
+ char *type_name = element_type_names[type];
TEXT type_result;
TEXT content_formatted;
+ HTML_DOCUMENT_CONTEXT *top_document_ctx = top_document_context (self);
+ HTML_FORMATTING_CONTEXT *top_formating_ctx
+ = top_html_formatting_context (&top_document_ctx->formatting_context);
text_init (&type_result);
text_append (&type_result, "");
- /* */
+ open_result = type_open (self, type, element);
+ if (open_result)
+ {
+ text_append (&type_result, open_result);
+ free (open_result);
+ }
+
+ if (type == ET_paragraph)
+ {
+ top_formating_ctx->paragraph_number++;
+ self->modified_state++;
+ }
+ else if (type == ET_preformatted || type == ET_rawpreformatted)
+ {
+ top_formating_ctx->preformatted_number++;
+ self->modified_state++;
+ }
+ else if (self->pre_class_types[type])
+ {
+ push_string_stack_string (&top_document_ctx->preformatted_classes,
+ self->pre_class_types[type]);
+ push_command_or_type (&top_document_ctx->composition_context,
+ 0, type);
+ self->modified_state++;
+ }
+
+ if (self->code_types[type])
+ {
+ push_monospace (&top_document_ctx->monospace_context);
+ self->modified_state++;
+ }
+
+ if (type == ET__string)
+ {
+ top_document_ctx->string_ctx++;
+ self->modified_state++;
+ }
text_init (&content_formatted);
- if (element->type == ET_definfoenclose_command)
+ if (type == ET_definfoenclose_command)
{
if (element->args.number > 0)
{
@@ -2554,21 +3131,40 @@ convert_to_html_internal (CONVERTER *self, ELEMENT
*element,
}
}
- if (self->types_conversion[element->type].status)
+ if (self->types_conversion[type].status)
{
- /*
- $result .= &{$self->{'types_conversion'}->{$type_name}} ($self,
- $type_name,
- $element,
- $content_formatted);
- */
+ char *result = type_conversion (self, type, element,
+ content_formatted.text);
+ if (result)
+ {
+ text_append (&type_result, result);
+ free (result);
+ }
}
else if (content_formatted.end > 0)
{
text_append (&type_result, content_formatted.text);
}
free (content_formatted.text);
- /* */
+
+ if (self->code_types[type])
+ {
+ pop_monospace_context (&top_document_ctx->monospace_context);
+ self->modified_state++;
+ }
+
+ if (type == ET__string)
+ {
+ top_document_ctx->string_ctx--;
+ self->modified_state++;
+ }
+
+ if (self->pre_class_types[type])
+ {
+ pop_string_stack (&top_document_ctx->preformatted_classes);
+ pop_command_or_type (&top_document_ctx->composition_context);
+ self->modified_state++;
+ }
if (self->conf->DEBUG > 0)
{
@@ -2647,6 +3243,7 @@ convert_output_unit (CONVERTER *self, OUTPUT_UNIT
*output_unit,
*/
self->current_output_unit = output_unit;
+ self->modified_state++;
text_init (&content_formatted);
text_append (&content_formatted, "");
@@ -2684,6 +3281,7 @@ convert_output_unit (CONVERTER *self, OUTPUT_UNIT
*output_unit,
}
self->current_output_unit = 0;
+ self->modified_state++;
if (self->conf->DEBUG > 0)
fprintf (stderr, "UNIT (%s) => `%s'\n", output_unit_type_names[unit_type],
@@ -2723,6 +3321,7 @@ html_convert_convert (CONVERTER *self, ELEMENT *root,
OUTPUT_UNIT_LIST *special_units
= retrieve_output_units (special_units_descriptor);
+ html_new_document_context (self, "_toplevel_context", 0, 0);
text_init (&result);
if (!output_units || !output_units->number)
@@ -2759,6 +3358,7 @@ html_convert_convert (CONVERTER *self, ELEMENT *root,
}
}
}
+ html_pop_document_context (self);
return result.text;
}
diff --git a/tp/Texinfo/XS/main/build_perl_info.c
b/tp/Texinfo/XS/main/build_perl_info.c
index d5a1efa5f3..8da67d8b9a 100644
--- a/tp/Texinfo/XS/main/build_perl_info.c
+++ b/tp/Texinfo/XS/main/build_perl_info.c
@@ -38,7 +38,7 @@
#include "tree_types.h"
#include "tree.h"
#include "element_types.h"
-/* for GLOBAL_INFO ERROR_MESSAGE fatal output_unit_type_names */
+/* for GLOBAL_INFO ERROR_MESSAGE fatal output_unit_type_names CONVERTER */
#include "utils.h"
/* for debugging */
#include "debug.h"
@@ -51,6 +51,7 @@
/* for wipe_error_message_list */
#include "errors.h"
#include "tree_perl_api.h"
+#include "command_stack.h"
#include "build_perl_info.h"
#define LOCALEDIR DATADIR "/locale"
@@ -1776,3 +1777,204 @@ build_out_filepaths (FILE_NAME_PATH_COUNTER_LIST
*output_unit_files)
return newRV_noinc ((SV *) hv);
}
+HV *
+build_html_formatting_context (HTML_FORMATTING_CONTEXT *formatting_context)
+{
+ HV *hv;
+
+ dTHX;
+
+ hv = newHV ();
+
+#define STORE(key, value) hv_store (hv, key, strlen (key), value, 0)
+
+ STORE("context_name", newSVpv (formatting_context->context_name, 0));
+#define STORE_INT(name) STORE(#name, newSViv (formatting_context->name))
+ STORE_INT(preformatted_number);
+ STORE_INT(paragraph_number);
+ STORE_INT(space_protected);
+ STORE_INT(no_break);
+#undef STORE_INT
+
+#define STORE_CTX(name) STORE(#name, newSViv (formatting_context->name##_ctx))
+ STORE_CTX(upper_case);
+#undef STORE_CTX
+
+#undef STORE
+ return hv;
+}
+
+HV *
+build_html_document_context (HTML_DOCUMENT_CONTEXT *document_context)
+{
+ int i;
+ HV *hv;
+ AV *monospace_context_av;
+ AV *composition_context_av;
+ AV *block_commands_av;
+ AV *formatting_context_av;
+ AV *preformatted_classes_av;
+
+ dTHX;
+
+ hv = newHV ();
+ monospace_context_av = newAV ();
+ composition_context_av = newAV ();
+ block_commands_av = newAV ();
+ formatting_context_av = newAV ();
+ preformatted_classes_av = newAV ();
+
+
+#define STORE(key, value) hv_store (hv, key, strlen (key), value, 0)
+
+ STORE ("context", newSVpv_utf8 (document_context->context, 0));
+
+#define STORE_CTX(name) STORE(#name, newSViv (document_context->name##_ctx))
+ STORE_CTX(string);
+ STORE_CTX(raw);
+ STORE_CTX(verbatim);
+ STORE_CTX(math);
+#undef STORE_CTX
+ STORE ("document_global_context",
+ newSViv (document_context->document_global_context));
+
+ for (i = 0; i < document_context->monospace_context.top; i++)
+ {
+ enum monospace_context context
+ = document_context->monospace_context.stack[i];
+ av_push (monospace_context_av, newSViv (context));
+ }
+
+ STORE ("monospace_context", newRV_noinc ((SV *) monospace_context_av));
+
+ for (i = 0; i < document_context->composition_context.top; i++)
+ {
+ char *context_str = 0;
+ COMMAND_OR_TYPE *context
+ = &document_context->composition_context.stack[i];
+ if (context->variety == CTV_type_type)
+ context_str = element_type_names[context->type];
+ else if (context->variety == CTV_type_command)
+ context_str = builtin_command_data[context->cmd].cmdname;
+ else
+ context_str = "";
+ av_push (composition_context_av, newSVpv (context_str, 0));
+ }
+ STORE ("composition_context", newRV_noinc ((SV *) composition_context_av));
+
+ for (i = 0; i < document_context->block_commands.top; i++)
+ {
+ enum command_id cmd = document_context->block_commands.stack[i];
+ char *context_str = builtin_command_data[cmd].cmdname;
+ av_push (block_commands_av, newSVpv (context_str, 0));
+ }
+ STORE ("block_commands", newRV_noinc ((SV *) block_commands_av));
+
+ for (i = 0; i < document_context->preformatted_classes.top; i++)
+ {
+ char *context_str = document_context->preformatted_classes.stack[i];
+ av_push (preformatted_classes_av, newSVpv (context_str, 0));
+ }
+ STORE ("preformatted_classes", newRV_noinc ((SV *) preformatted_classes_av));
+
+ for (i = 0; i < document_context->formatting_context.top; i++)
+ {
+ HTML_FORMATTING_CONTEXT *formatting_context
+ = &document_context->formatting_context.stack[i];
+ HV *context_hv = build_html_formatting_context (formatting_context);
+ av_push (formatting_context_av, newRV_noinc ((SV *) context_hv));
+ }
+ STORE ("formatting_context", newRV_noinc ((SV *) formatting_context_av));
+
+#undef STORE
+ return hv;
+}
+
+/* there is no need to return anything. */
+SV *
+build_html_formatting_state (CONVERTER *converter)
+{
+ HV *hv;
+ SV **document_context_sv;
+ AV *document_context_av;
+ SV **files_information_sv;
+ HV *files_information_hv;
+ int i;
+
+ dTHX;
+
+ if (!converter->hv)
+ return newSV (0);
+
+ hv = converter->hv;
+
+#define STORE(key, value) hv_store (hv, key, strlen (key), value, 0)
+ STORE("document_global_context",
+ newSViv (converter->document_global_context));
+
+ if (!converter->current_root_command)
+ STORE("current_root_command", newSV (0));
+ else
+ STORE("current_root_command",
+ newRV_inc ((SV *) converter->current_root_command->hv));
+
+ if (!converter->current_node)
+ STORE("current_node", newSV (0));
+ else
+ STORE("current_node",
+ newRV_inc ((SV *) converter->current_node->hv));
+
+ if (!converter->current_output_unit)
+ STORE("current_output_unit", newSV (0));
+ else
+ STORE("current_output_unit",
+ newRV_inc ((SV *) converter->current_output_unit->hv));
+
+ if (!converter->current_filename)
+ STORE("current_filename", newSV (0));
+ else
+ STORE("current_filename", newSVpv_utf8 (converter->current_filename, 0));
+
+ document_context_sv = hv_fetch (hv, "document_context",
+ strlen ("document_context"), 0);
+
+ if (!document_context_sv)
+ {
+ document_context_av = newAV ();
+ STORE("document_context", newRV_noinc ((SV *) document_context_av));
+ }
+ else
+ {
+ document_context_av = (AV *) SvRV (*document_context_sv);
+ av_clear (document_context_av);
+ }
+
+ for (i = 0; i < converter->html_document_context.top; i++)
+ {
+ HTML_DOCUMENT_CONTEXT *document_context
+ = &converter->html_document_context.stack[i];
+ HV *document_context_hv = build_html_document_context (document_context);
+ av_push (document_context_av, newRV_noinc ((SV *) document_context_hv));
+ }
+
+ files_information_sv = hv_fetch (hv, "files_information",
+ strlen ("files_information"), 0);
+
+ if (!files_information_sv)
+ {
+ files_information_hv = newHV ();
+ STORE("files_information", newRV_noinc ((SV *) files_information_hv));
+ }
+ else
+ {
+ /* TODO
+ files_information_hv = (HV *) SvRV (*files_information_sv);
+ hv_clear (files_information_av);
+ */
+ }
+
+
+#undef STORE
+
+ return newRV_noinc ((SV *) hv);
+}
diff --git a/tp/Texinfo/XS/main/build_perl_info.h
b/tp/Texinfo/XS/main/build_perl_info.h
index 4aab36f540..421aa65d40 100644
--- a/tp/Texinfo/XS/main/build_perl_info.h
+++ b/tp/Texinfo/XS/main/build_perl_info.h
@@ -48,4 +48,5 @@ SV *build_filenames (FILE_NAME_PATH_COUNTER_LIST
*output_unit_files);
SV *build_file_counters (FILE_NAME_PATH_COUNTER_LIST *output_unit_files);
SV *build_out_filepaths (FILE_NAME_PATH_COUNTER_LIST *output_unit_files);
+SV *build_html_formatting_state (CONVERTER *converter);
#endif
diff --git a/tp/Texinfo/XS/main/call_perl_function.c
b/tp/Texinfo/XS/main/call_perl_function.c
index ac763204ae..9c661a4422 100644
--- a/tp/Texinfo/XS/main/call_perl_function.c
+++ b/tp/Texinfo/XS/main/call_perl_function.c
@@ -527,3 +527,122 @@ call_formatting_function_format_title_titlepage
(CONVERTER *self)
return result;
}
+
+char *
+call_types_conversion (CONVERTER *self, enum element_type type,
+ ELEMENT *element, char *content)
+{
+ int count;
+ char *result;
+ char *result_ret;
+ STRLEN len;
+ SV *result_sv;
+ SV *formatting_reference = self->types_conversion[type].sv_reference;
+
+ dTHX;
+
+ if (!self->hv)
+ return 0;
+
+ if (self->modified_state)
+ {
+ build_html_formatting_state (self);
+ self->modified_state = 0;
+ }
+
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ EXTEND(SP, 4);
+
+ PUSHs(sv_2mortal (newRV_inc (self->hv)));
+ PUSHs(sv_2mortal (newSVpv (element_type_names[type], 0)));
+ PUSHs(sv_2mortal (newRV_inc (element->hv)));
+ /* content == 0 is possible, hope that newSVpv result corresponds to
+ undef in that case, but could also need to explicitely use newSV(0) */
+ PUSHs(sv_2mortal (newSVpv_utf8 (content, 0)));
+ PUTBACK;
+
+ count = call_sv (formatting_reference,
+ G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1)
+ croak("types_conversion should return 1 item\n");
+
+ result_sv = POPs;
+ /* it is encoded using non strict encoding, so the UTF-8 could be invalid.
+ It could be possible to add a wrapper in perl that encode to UTF-8,
+ but probably not worth it */
+ result_ret = SvPVutf8 (result_sv, len);
+ result = strdup (result_ret);
+
+ PUTBACK;
+
+ FREETMPS;
+ LEAVE;
+
+ return result;
+}
+
+char *
+call_types_open (CONVERTER *self, enum element_type type,
+ ELEMENT *element)
+{
+ int count;
+ char *result;
+ char *result_ret;
+ STRLEN len;
+ SV *result_sv;
+ SV *formatting_reference = self->types_open[type].sv_reference;
+
+ dTHX;
+
+ if (!self->hv)
+ return 0;
+
+ if (self->modified_state)
+ {
+ build_html_formatting_state (self);
+ self->modified_state = 0;
+ }
+
+ dSP;
+
+ ENTER;
+ SAVETMPS;
+
+ PUSHMARK(SP);
+ EXTEND(SP, 3);
+
+ PUSHs(sv_2mortal (newRV_inc (self->hv)));
+ PUSHs(sv_2mortal (newSVpv (element_type_names[type], 0)));
+ PUSHs(sv_2mortal (newRV_inc (element->hv)));
+ PUTBACK;
+
+ count = call_sv (formatting_reference,
+ G_SCALAR);
+
+ SPAGAIN;
+
+ if (count != 1)
+ croak("types_open should return 1 item\n");
+
+ result_sv = POPs;
+ /* it is encoded using non strict encoding, so the UTF-8 could be invalid.
+ It could be possible to add a wrapper in perl that encode to UTF-8,
+ but probably not worth it */
+ result_ret = SvPVutf8 (result_sv, len);
+ result = strdup (result_ret);
+
+ PUTBACK;
+
+ FREETMPS;
+ LEAVE;
+
+ return result;
+}
diff --git a/tp/Texinfo/XS/main/command_stack.c
b/tp/Texinfo/XS/main/command_stack.c
index 478167aa66..eb1b873a95 100644
--- a/tp/Texinfo/XS/main/command_stack.c
+++ b/tp/Texinfo/XS/main/command_stack.c
@@ -15,6 +15,7 @@
#include <config.h>
#include <stdlib.h>
+#include <string.h>
#include "tree_types.h"
#include "command_ids.h"
@@ -64,17 +65,132 @@ top_command (COMMAND_STACK *stack)
return stack->stack[stack->top - 1];
}
-enum command_id
-current_context_command (void)
+void
+push_command_or_type (COMMAND_OR_TYPE_STACK *stack, enum command_id cmd,
+ enum element_type type)
{
- int i;
+ if (stack->top >= stack->space)
+ {
+ stack->stack
+ = realloc (stack->stack,
+ (stack->space += 5) * sizeof (COMMAND_OR_TYPE));
+ }
- if (top == 0)
- return CM_NONE;
- for (i = top -1; i >= 0; i--)
+ if (type)
+ {
+ stack->stack[stack->top].type = type;
+ stack->stack[stack->top].variety = CTV_type_type;
+ }
+ else if (cmd)
+ {
+ stack->stack[stack->top].cmd = cmd;
+ stack->stack[stack->top].variety = CTV_type_command;
+ }
+ else
{
- if (command_stack.stack[i] != CM_NONE)
- return command_stack.stack[i];
+ stack->stack[stack->top].cmd = 0;
+ stack->stack[stack->top].variety = CTV_type_none;
}
- return CM_NONE;
+
+ stack->top++;
+}
+
+void
+pop_command_or_type (COMMAND_OR_TYPE_STACK *stack)
+{
+ if (stack->top == 0)
+ fatal ("command or type stack empty");
+
+ stack->top--;
}
+
+COMMAND_OR_TYPE *
+top_command_or_type (COMMAND_OR_TYPE_STACK *stack)
+{
+ if (stack->top == 0)
+ fatal ("command or type stack empty for top");
+
+ return &stack->stack[stack->top - 1];
+}
+
+
+void
+push_string_stack_string (STRING_STACK *stack, char *string)
+{
+ if (stack->top >= stack->space)
+ {
+ stack->stack
+ = realloc (stack->stack,
+ (stack->space += 5) * sizeof (char *));
+ }
+
+ stack->stack[stack->top] = strdup (string);
+
+ stack->top++;
+}
+
+void
+pop_string_stack (STRING_STACK *stack)
+{
+ if (stack->top == 0)
+ fatal ("string stack empty");
+
+ free (stack->stack[stack->top - 1]);
+ stack->top--;
+}
+
+char *
+top_string_stack (STRING_STACK *stack)
+{
+ if (stack->top == 0)
+ fatal ("string stack empty for top");
+
+ return stack->stack[stack->top - 1];
+}
+
+
+static void
+push_monospace_context (MONOSPACE_CONTEXT_STACK *stack,
+ enum monospace_context mono_ctx)
+{
+ if (stack->top >= stack->space)
+ {
+ stack->stack
+ = realloc (stack->stack,
+ (stack->space += 5) * sizeof (enum monospace_context));
+ }
+
+ stack->stack[stack->top] = mono_ctx;
+ stack->top++;
+}
+
+void
+push_monospace (MONOSPACE_CONTEXT_STACK *stack)
+{
+ push_monospace_context (stack, MONO_ctx_on);
+}
+
+void
+push_style_no_code (MONOSPACE_CONTEXT_STACK *stack)
+{
+ push_monospace_context (stack, MONO_ctx_off);
+}
+
+enum monospace_context
+pop_monospace_context (MONOSPACE_CONTEXT_STACK *stack)
+{
+ if (stack->top == 0)
+ fatal ("monospace stack empty for top");
+
+ return stack->stack[--stack->top];
+}
+
+enum monospace_context
+top_monospace_context (MONOSPACE_CONTEXT_STACK *stack)
+{
+ if (stack->top == 0)
+ fatal ("monospace stack empty for top");
+
+ return stack->stack[stack->top - 1];
+}
+
diff --git a/tp/Texinfo/XS/main/command_stack.h
b/tp/Texinfo/XS/main/command_stack.h
index f9e5287c57..0a5b3bf20d 100644
--- a/tp/Texinfo/XS/main/command_stack.h
+++ b/tp/Texinfo/XS/main/command_stack.h
@@ -19,10 +19,22 @@
#include <stddef.h>
#include "tree_types.h"
+#include "element_types.h"
+
+enum command_type_variety {
+ CTV_type_none,
+ CTV_type_command,
+ CTV_type_type,
+};
+
+enum monospace_context {
+ MONO_ctx_off,
+ MONO_ctx_on,
+};
typedef struct {
enum command_id *stack;
- size_t top; /* One above last pushed context. */
+ size_t top; /* One above last pushed command. */
size_t space;
} COMMAND_STACK;
@@ -30,6 +42,48 @@ void reset_command_stack (COMMAND_STACK *stack);
void push_command (COMMAND_STACK *stack, enum command_id cmd);
enum command_id pop_command (COMMAND_STACK *stack);
enum command_id top_command (COMMAND_STACK *stack);
-enum command_id current_context_command (void);
+
+/* either a type or a command id */
+typedef struct {
+ enum command_type_variety variety;
+ union {
+ enum command_id cmd;
+ enum element_type type;
+ };
+} COMMAND_OR_TYPE;
+
+typedef struct {
+ COMMAND_OR_TYPE *stack;
+ size_t top; /* One above last pushed command. */
+ size_t space;
+} COMMAND_OR_TYPE_STACK;
+
+void push_command_or_type (COMMAND_OR_TYPE_STACK *stack, enum command_id cmd,
+ enum element_type type);
+void pop_command_or_type (COMMAND_OR_TYPE_STACK *stack);
+COMMAND_OR_TYPE *top_command_or_type (COMMAND_OR_TYPE_STACK *stack);
+
+
+typedef struct {
+ char **stack;
+ size_t top; /* One above last pushed command. */
+ size_t space;
+} STRING_STACK;
+
+void push_string_stack_string (STRING_STACK *stack, char *string);
+void pop_string_stack (STRING_STACK *stack);
+char *top_string_stack (STRING_STACK *stack);
+
+
+typedef struct {
+ enum monospace_context *stack;
+ size_t top; /* One above last pushed. */
+ size_t space;
+} MONOSPACE_CONTEXT_STACK;
+
+void push_monospace (MONOSPACE_CONTEXT_STACK *stack);
+void push_style_no_code (MONOSPACE_CONTEXT_STACK *stack);
+enum monospace_context pop_monospace_context (MONOSPACE_CONTEXT_STACK *stack);
+enum monospace_context top_monospace_context (MONOSPACE_CONTEXT_STACK *stack);
#endif
diff --git a/tp/Texinfo/XS/main/element_types.c
b/tp/Texinfo/XS/main/element_types.c
index 8a47d991ad..410cd47d49 100644
--- a/tp/Texinfo/XS/main/element_types.c
+++ b/tp/Texinfo/XS/main/element_types.c
@@ -71,6 +71,9 @@ char *element_type_names[] = {
"macro_call",
"rmacro_call",
"linemacro_call",
+"_code",
+"_converted",
+"_string",
"special_unit_element",
};
diff --git a/tp/Texinfo/XS/main/element_types.h
b/tp/Texinfo/XS/main/element_types.h
index aa0ec079a5..c3e7a74fb2 100644
--- a/tp/Texinfo/XS/main/element_types.h
+++ b/tp/Texinfo/XS/main/element_types.h
@@ -74,6 +74,9 @@ ET_untranslated,
ET_macro_call,
ET_rmacro_call,
ET_linemacro_call,
+ET__code,
+ET__converted,
+ET__string,
ET_special_unit_element,
};
diff --git a/tp/Texinfo/XS/main/element_types.txt
b/tp/Texinfo/XS/main/element_types.txt
index 778f15e5f8..8769b50fe9 100644
--- a/tp/Texinfo/XS/main/element_types.txt
+++ b/tp/Texinfo/XS/main/element_types.txt
@@ -103,6 +103,14 @@ macro_call
rmacro_call
linemacro_call
+# for HTML converter
+_code
+_converted
+_string
+
# not in parser, for virtual element associated to special output units
+# the corresponding type is often used in code to determine the number of
+# element types, so it would be a good idea to keep special_unit_element
+# last.
special_unit_element
diff --git a/tp/Texinfo/XS/main/get_perl_info.c
b/tp/Texinfo/XS/main/get_perl_info.c
index 7bf4a994d7..bdcbf18dcc 100644
--- a/tp/Texinfo/XS/main/get_perl_info.c
+++ b/tp/Texinfo/XS/main/get_perl_info.c
@@ -454,6 +454,8 @@ html_converter_initialize_sv (SV *sv_in, SV
*default_formatting_references,
SV **types_conversion_sv;
SV **commands_open_sv;
SV **commands_conversion_sv;
+ SV **code_types_sv;
+ SV **pre_class_types_sv;
HV *formatting_function_hv;
HV *commands_open_hv;
HV *commands_conversion_hv;
@@ -612,7 +614,6 @@ html_converter_initialize_sv (SV *sv_in, SV
*default_formatting_references,
types_conversion_hv);
}
-
FETCH(sorted_special_unit_varieties)
if (sorted_special_unit_varieties_sv)
@@ -716,6 +717,98 @@ html_converter_initialize_sv (SV *sv_in, SV
*default_formatting_references,
memset (converter->global_units_directions, 0,
(D_Last + nr_special_units+1) * sizeof (OUTPUT_UNIT));
+ FETCH(code_types)
+
+ if (code_types_sv)
+ {
+ I32 hv_number;
+ I32 i;
+
+ HV *code_types_hv = (HV *)SvRV (*code_types_sv);
+
+ hv_number = hv_iterinit (code_types_hv);
+
+ for (i = 0; i < hv_number; i++)
+ {
+ int j;
+ enum element_type type = ET_NONE;
+ I32 retlen;
+ char *type_name;
+ SV *code_sv = hv_iternextsv (code_types_hv,
+ &type_name, &retlen);
+ if (SvOK (code_sv))
+ {
+ int code_value = SvIV (code_sv);
+ /* this is not very efficient, but should be done only once
+ in the default case. If this is needed more, a qsort/bfind
+ could be used, but the overhead could probably only be
+ justified if finding the type index happens more often */
+ for (j = 1; j < ET_special_unit_element+1; j++)
+ {
+ if (!strcmp (element_type_names[j], type_name))
+ {
+ type = j;
+ break;
+ }
+ }
+ if (type == ET_NONE)
+ {
+ fprintf (stderr, "ERROR: %s: code type not found\n",
+ type_name);
+ }
+ else
+ converter->code_types[type] = code_value;
+ }
+ }
+ }
+
+ FETCH(pre_class_types)
+
+ if (pre_class_types_sv)
+ {
+ I32 hv_number;
+ I32 i;
+
+ HV *pre_class_types_hv = (HV *)SvRV (*pre_class_types_sv);
+
+ hv_number = hv_iterinit (pre_class_types_hv);
+
+ for (i = 0; i < hv_number; i++)
+ {
+ int j;
+ I32 retlen;
+ char *type_name;
+ SV *pre_class_sv = hv_iternextsv (pre_class_types_hv,
+ &type_name, &retlen);
+ if (SvOK (pre_class_sv))
+ {
+ enum element_type type = ET_NONE;
+ char *pre_class = SvPV_nolen (pre_class_sv);
+ /* this is not very efficient, but should be done only once
+ in the default case. If this is needed more, a qsort/bfind
+ could be used, but the overhead could probably only be
+ justified if finding the type index happens more often */
+ for (j = 1; j < ET_special_unit_element+1; j++)
+ {
+ if (!strcmp (element_type_names[j], type_name))
+ {
+ type = j;
+ break;
+ }
+ }
+ if (type == ET_NONE)
+ {
+ fprintf (stderr, "ERROR: %s: pre class type not found\n",
+ type_name);
+ }
+ else
+ converter->pre_class_types[type] = strdup (pre_class);
+ }
+ }
+ }
+
+
+
FETCH(no_arg_commands_formatting)
if (no_arg_commands_formatting_sv)
diff --git a/tp/Texinfo/XS/main/translations.h
b/tp/Texinfo/XS/main/translations.h
index 8d0d445477..bbb45f1dab 100644
--- a/tp/Texinfo/XS/main/translations.h
+++ b/tp/Texinfo/XS/main/translations.h
@@ -35,10 +35,10 @@ char *gdt_string (char *string, OPTIONS *options,
NAMED_STRING_ELEMENT_LIST *replaced_substrings,
const char *translation_context, char *in_lang);
-ELEMENT * pgdt_tree (const char *translation_context, char *string,
- DOCUMENT *document, OPTIONS *options,
- NAMED_STRING_ELEMENT_LIST *replaced_substrings,
- char *in_lang);
+ELEMENT *pgdt_tree (const char *translation_context, char *string,
+ DOCUMENT *document, OPTIONS *options,
+ NAMED_STRING_ELEMENT_LIST *replaced_substrings,
+ char *in_lang);
NAMED_STRING_ELEMENT_LIST * new_named_string_element_list (void);
void add_string_to_named_string_element_list (NAMED_STRING_ELEMENT_LIST *nsel,
diff --git a/tp/Texinfo/XS/main/tree_perl_api.h
b/tp/Texinfo/XS/main/tree_perl_api.h
index 1c1bb0ed70..4e6bf3e878 100644
--- a/tp/Texinfo/XS/main/tree_perl_api.h
+++ b/tp/Texinfo/XS/main/tree_perl_api.h
@@ -29,4 +29,9 @@ FILE_NAME_PATH *call_file_id_setting_unit_file_name
(CONVERTER *self,
char *filename, char *filepath);
char *call_formatting_function_format_title_titlepage (CONVERTER *self);
+char *call_types_conversion (CONVERTER *self, enum element_type type,
+ ELEMENT *element, char *content);
+char *call_types_open (CONVERTER *self, enum element_type type,
+ ELEMENT *element);
+
#endif
diff --git a/tp/Texinfo/XS/main/utils.c b/tp/Texinfo/XS/main/utils.c
index b91c156386..e50c5cf498 100644
--- a/tp/Texinfo/XS/main/utils.c
+++ b/tp/Texinfo/XS/main/utils.c
@@ -56,6 +56,13 @@ const char *direction_names[] = {"next", "prev", "up"};
const char *direction_texts[] = {"Next", "Prev", "Up"};
const size_t directions_length = sizeof (direction_names) / sizeof
(direction_names[0]);
+const enum command_id small_block_associated_command[][2] = {
+ #define smbc_command_name(name) {CM_small##name, CM_##name},
+ SMALL_BLOC_COMMANDS_LIST
+ #undef smbc_command_name
+ {0, 0},
+};
+
/* to keep synchronized with enum output_unit_type in tree_types.h */
const char *output_unit_type_names[] = {"unit",
"external_node_unit",
diff --git a/tp/Texinfo/XS/main/utils.h b/tp/Texinfo/XS/main/utils.h
index d0510e48e8..730598f22e 100644
--- a/tp/Texinfo/XS/main/utils.h
+++ b/tp/Texinfo/XS/main/utils.h
@@ -24,6 +24,7 @@
#include "global_commands_types.h"
#include "tree_types.h"
#include "command_ids.h"
+#include "command_stack.h"
#include "builtin_commands.h"
extern const char *whitespace_chars;
@@ -125,6 +126,16 @@ typedef struct COMMAND_OPTION_VALUE {
};
} COMMAND_OPTION_VALUE;
+#define SMALL_BLOC_COMMANDS_LIST \
+ smbc_command_name(example)\
+ smbc_command_name(display) \
+ smbc_command_name(format) \
+ smbc_command_name(lisp) \
+ smbc_command_name(quotation) \
+ smbc_command_name(indentedblock)
+
+extern const enum command_id small_block_associated_command[][2];
+
/* CONVERTER and associated types needed for set_global_document_command */
/* see Texinfo::HTML _prepare_output_units_global_targets
@@ -363,6 +374,41 @@ typedef struct FORMATTING_REFERENCE {
enum formatting_reference_status status;
} FORMATTING_REFERENCE;
+typedef struct HTML_FORMATTING_CONTEXT {
+ char *context_name;
+ int preformatted_number;
+ int paragraph_number;
+ int upper_case_ctx;
+ int space_protected;
+ int no_break;
+} HTML_FORMATTING_CONTEXT;
+
+typedef struct HTML_FORMATTING_CONTEXT_STACK {
+ HTML_FORMATTING_CONTEXT *stack;
+ size_t top; /* One above last pushed context. */
+ size_t space;
+} HTML_FORMATTING_CONTEXT_STACK;
+
+typedef struct HTML_DOCUMENT_CONTEXT {
+ char *context;
+ int string_ctx;
+ int raw_ctx;
+ int verbatim_ctx;
+ int math_ctx;
+ int document_global_context;
+ MONOSPACE_CONTEXT_STACK monospace_context;
+ COMMAND_OR_TYPE_STACK composition_context;
+ COMMAND_STACK block_commands;
+ HTML_FORMATTING_CONTEXT_STACK formatting_context;
+ STRING_STACK preformatted_classes;
+} HTML_DOCUMENT_CONTEXT;
+
+typedef struct HTML_DOCUMENT_CONTEXT_STACK {
+ HTML_DOCUMENT_CONTEXT *stack;
+ size_t top; /* One above last pushed context. */
+ size_t space;
+} HTML_DOCUMENT_CONTEXT_STACK;
+
typedef struct CONVERTER {
int converter_descriptor;
OPTIONS *conf;
@@ -378,6 +424,8 @@ typedef struct CONVERTER {
/* output unit files API */
FILE_NAME_PATH_COUNTER_LIST *output_unit_files;
+ int modified_state; /* to determine if perl data should be rebuilt */
+
/* perl converter. This should be HV *hv,
but we don't want to include the Perl headers everywhere; */
void *hv;
@@ -386,8 +434,6 @@ typedef struct CONVERTER {
char *title_titlepage;
/* HTML specific */
- ELEMENT *current_root_command;
- OUTPUT_UNIT *current_output_unit;
OUTPUT_UNIT **global_units_directions;
SPECIAL_UNIT_DIRECTION **special_units_direction_name;
char **special_unit_info[SUI_type_heading+1];
@@ -400,6 +446,8 @@ typedef struct CONVERTER {
char **directions_strings[TDS_type_rel+1];
HTML_COMMAND_CONVERSION **html_command_conversion[BUILTIN_CMD_NUMBER];
COMMAND_ID_LIST *no_arg_formatted_cmd;
+ int code_types[ET_special_unit_element+1];
+ char *pre_class_types[ET_special_unit_element+1];
FORMATTING_REFERENCE
formatting_references[FR_format_translate_message_string+1];
FORMATTING_REFERENCE
@@ -408,6 +456,14 @@ typedef struct CONVERTER {
FORMATTING_REFERENCE commands_conversion[BUILTIN_CMD_NUMBER];
FORMATTING_REFERENCE types_open[ET_special_unit_element+1];
FORMATTING_REFERENCE types_conversion[ET_special_unit_element+1];
+
+ /* state */
+ int document_global_context;
+ ELEMENT *current_root_command;
+ ELEMENT *current_node;
+ OUTPUT_UNIT *current_output_unit;
+ HTML_DOCUMENT_CONTEXT_STACK html_document_context;
+ char *current_filename;
} CONVERTER;
typedef struct TARGET_FILENAME {
diff --git a/tp/Texinfo/XS/parsetexi/api.c b/tp/Texinfo/XS/parsetexi/api.c
index dddb2aeb4e..6e62d5fef4 100644
--- a/tp/Texinfo/XS/parsetexi/api.c
+++ b/tp/Texinfo/XS/parsetexi/api.c
@@ -43,6 +43,7 @@
#include "document.h"
/* for wipe_user_commands */
#include "commands.h"
+#include "command_stack.h"
#include "context_stack.h"
/* for clear_parser_expanded_formats and add_parser_expanded_format */
#include "handle_commands.h"
diff --git a/tp/Texinfo/XS/parsetexi/close.c b/tp/Texinfo/XS/parsetexi/close.c
index cfad12ec18..35d660117b 100644
--- a/tp/Texinfo/XS/parsetexi/close.c
+++ b/tp/Texinfo/XS/parsetexi/close.c
@@ -30,6 +30,7 @@
#include "counter.h"
#include "builtin_commands.h"
#include "source_marks.h"
+#include "command_stack.h"
#include "context_stack.h"
#include "extra.h"
diff --git a/tp/Texinfo/XS/parsetexi/context_stack.c
b/tp/Texinfo/XS/parsetexi/context_stack.c
index a47131a63c..47c617aba2 100644
--- a/tp/Texinfo/XS/parsetexi/context_stack.c
+++ b/tp/Texinfo/XS/parsetexi/context_stack.c
@@ -16,10 +16,13 @@
#include <config.h>
#include <stdlib.h>
+#include "tree_types.h"
+#include "command_ids.h"
+#include "utils.h"
+#include "commands.h"
#include "debug.h"
+#include "command_stack.h"
#include "context_stack.h"
-#include "commands.h"
-#include "utils.h"
static enum context *context_stack;
static size_t top; /* One above last pushed context. */
@@ -28,49 +31,6 @@ static size_t space;
/* Kept in sync with context_stack. */
static COMMAND_STACK command_stack;
-/* Generic command stack functions */
-
-void
-reset_command_stack (COMMAND_STACK *stack)
-{
- stack->top = 0;
- stack->space = 0;
- free (stack->stack);
- stack->stack = 0;
-}
-
-void
-push_command (COMMAND_STACK *stack, enum command_id cmd)
-{
- if (stack->top >= stack->space)
- {
- stack->stack
- = realloc (stack->stack,
- (stack->space += 5) * sizeof (enum command_id));
- }
-
- stack->stack[stack->top] = cmd;
- stack->top++;
-}
-
-enum command_id
-pop_command (COMMAND_STACK *stack)
-{
- if (stack->top == 0)
- fatal ("command stack empty");
-
- return stack->stack[--stack->top];
-}
-
-enum command_id
-top_command (COMMAND_STACK *stack)
-{
- if (stack->top == 0)
- fatal ("command stack empty for top");
-
- return stack->stack[stack->top - 1];
-}
-
enum command_id
current_context_command (void)
{
@@ -85,7 +45,6 @@ current_context_command (void)
}
return CM_NONE;
}
-
/* Context stacks */
void
diff --git a/tp/Texinfo/XS/parsetexi/context_stack.h
b/tp/Texinfo/XS/parsetexi/context_stack.h
index 09fcde5ff5..ab8c29b020 100644
--- a/tp/Texinfo/XS/parsetexi/context_stack.h
+++ b/tp/Texinfo/XS/parsetexi/context_stack.h
@@ -19,6 +19,7 @@
#include <stddef.h>
#include "tree_types.h"
+#include "command_stack.h"
enum context {
ct_NONE,
@@ -39,6 +40,8 @@ enum context {
|| (c) == ct_rawpreformatted \
|| (c) == ct_inlineraw)
+enum command_id current_context_command (void);
+
void push_context (enum context c, enum command_id cmd);
enum context pop_context (void);
enum context current_context (void);
@@ -49,19 +52,6 @@ char *context_name (enum context c);
-typedef struct {
- enum command_id *stack;
- size_t top; /* One above last pushed context. */
- size_t space;
-} COMMAND_STACK;
-
-void reset_command_stack (COMMAND_STACK *stack);
-void push_command (COMMAND_STACK *stack, enum command_id cmd);
-enum command_id pop_command (COMMAND_STACK *stack);
-enum command_id top_command (COMMAND_STACK *stack);
-enum command_id current_context_command (void);
-
-
/* Used to check indirect nesting, e.g. @footnote{@emph{@footnote{...}}} */
typedef struct {
int footnote;
diff --git a/tp/Texinfo/XS/parsetexi/end_line.c
b/tp/Texinfo/XS/parsetexi/end_line.c
index 54f5880625..e16a1ebbd5 100644
--- a/tp/Texinfo/XS/parsetexi/end_line.c
+++ b/tp/Texinfo/XS/parsetexi/end_line.c
@@ -41,6 +41,7 @@
/* add_infoenclose */
#include "macro.h"
#include "indices.h"
+#include "command_stack.h"
#include "context_stack.h"
#include "builtin_commands.h"
#include "commands.h"
diff --git a/tp/Texinfo/XS/parsetexi/handle_commands.c
b/tp/Texinfo/XS/parsetexi/handle_commands.c
index 6c93460087..69f26c6b24 100644
--- a/tp/Texinfo/XS/parsetexi/handle_commands.c
+++ b/tp/Texinfo/XS/parsetexi/handle_commands.c
@@ -28,6 +28,7 @@
/* for isascii_alnum whitespace_chars read_flag_name item_line_parent */
#include "utils.h"
#include "counter.h"
+#include "command_stack.h"
#include "context_stack.h"
/* for conf */
#include "conf.h"
diff --git a/tp/Texinfo/XS/parsetexi/indices.c
b/tp/Texinfo/XS/parsetexi/indices.c
index 113b69221b..a2478e7f48 100644
--- a/tp/Texinfo/XS/parsetexi/indices.c
+++ b/tp/Texinfo/XS/parsetexi/indices.c
@@ -26,6 +26,7 @@
/* for xasprintf and other */
#include "errors.h"
#include "debug.h"
+#include "command_stack.h"
#include "context_stack.h"
#include "builtin_commands.h"
#include "extra.h"
diff --git a/tp/Texinfo/XS/parsetexi/parser.c b/tp/Texinfo/XS/parsetexi/parser.c
index 46ceec0a9f..ea542f0107 100644
--- a/tp/Texinfo/XS/parsetexi/parser.c
+++ b/tp/Texinfo/XS/parsetexi/parser.c
@@ -42,6 +42,7 @@
#include "extra.h"
/* for conf */
#include "conf.h"
+#include "command_stack.h"
/* for nesting_context */
#include "context_stack.h"
#include "commands.h"
diff --git a/tp/Texinfo/XS/parsetexi/separator.c
b/tp/Texinfo/XS/parsetexi/separator.c
index 38a554b903..c0f2720991 100644
--- a/tp/Texinfo/XS/parsetexi/separator.c
+++ b/tp/Texinfo/XS/parsetexi/separator.c
@@ -28,6 +28,7 @@
#include "debug.h"
#include "debug_parser.h"
#include "errors.h"
+#include "command_stack.h"
#include "context_stack.h"
/* for parse_node_manual */
#include "manipulate_tree.h"