/* Copyright 2010-2024 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 the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include "global_commands_types.h" #include "tree_types.h" /* new_element */ #include "tree.h" /* for wipe_values ... */ #include "utils.h" #include "command_stack.h" #include "errors.h" #include "document.h" /* for global_parser_conf */ #include "parser_conf.h" /* for wipe_user_commands */ #include "commands.h" #include "context_stack.h" /* for set_input_file_name_encoding ... */ #include "source_marks.h" #include "input.h" /* for wipe_macros store_value init_values */ #include "macro.h" /* for reset_conf */ #include "conf.h" #include "parser.h" /* for init_index_commands */ #include "indices.h" #include "api.h" static size_t initialize_parsing (enum context root_ct) { parsed_document = new_document (); if (!global_parser_conf.no_index) init_index_commands (); wipe_user_commands (); wipe_macros (); /* initialize from conf */ init_values (); /* currently there is no change done to include directories, so global_parser_conf.include_directories could be used instead of parser_include_directories */ clear_strings_list (&parser_include_directories); copy_strings (&parser_include_directories, &global_parser_conf.include_directories); free (global_documentlanguage); if (global_parser_conf.global_documentlanguage_fixed && global_parser_conf.documentlanguage) global_documentlanguage = strdup (global_parser_conf.documentlanguage); else global_documentlanguage = 0; /* initialize document state */ free (global_clickstyle); global_clickstyle = strdup ("arrow"); global_kbdinputstyle = kbd_distinct; current_node = 0; current_section = 0; current_part = 0; source_marks_reset_counters (); parser_reset_encoding_list (); set_input_encoding ("utf-8"); /* initialize parsing state */ reset_context_stack (); push_context (root_ct, CM_NONE); reset_command_stack (&nesting_context.basic_inline_stack); reset_command_stack (&nesting_context.basic_inline_stack_on_line); reset_command_stack (&nesting_context.basic_inline_stack_block); reset_command_stack (&nesting_context.regions_stack); memset (&nesting_context, 0, sizeof (nesting_context)); reset_parser_counters (); return parsed_document->descriptor; } void reset_parser (int local_debug_output) { /* We cannot call debug () here, because the configuration of the previous parser invokation has not been reset already, and new configuration has not been read, so we need to pass the configuration information directly */ /* debug ("!!!!!!!!!!!!!!!! RESETTING THE PARSER !!!!!!!!!!!!!!!!!!!!!"); */ if (local_debug_output) fprintf (stderr, "!!!!!!!!!!!!!!!! RESETTING THE PARSER !!!!!!!!!!!!!!!!!!!!!\n"); reset_parser_conf (); } /* Determine directory path based on file name. Return a DOCUMENT_DESCRIPTOR that can be used to retrieve the tree and document obtained by parsing INPUT_FILE_PATH. STATUS is set to non zero if parsing could not proceed. It is always the responsibility of the caller to get the error messages and destroy the document. Used for parse_texi_file. */ size_t parse_file (const char *input_file_path, int *status) { size_t document_descriptor = initialize_parsing (ct_base); GLOBAL_INFO *global_info; char *input_file_name_and_directory[2]; int input_error; parse_file_path (input_file_path, input_file_name_and_directory); global_info = &parsed_document->global_info; free (global_info->input_file_name); free (global_info->input_directory); global_info->input_file_name = input_file_name_and_directory[0]; global_info->input_directory = input_file_name_and_directory[1]; input_error = input_push_file (input_file_path); if (input_error) { char *decoded_file_path; if (global_parser_conf.command_line_encoding) { int status; /* cast as decode_string argument should not be modified but cannot be marked as const */ decoded_file_path = decode_string ((char *)input_file_path, global_parser_conf.command_line_encoding, &status, 0); } else decoded_file_path = strdup (input_file_path); message_list_document_error (&parsed_document->parser_error_messages, 0, 0, "could not open %s: %s", decoded_file_path, strerror (input_error)); free (decoded_file_path); *status = 1; return document_descriptor; } parse_texi_document (); *status = 0; return document_descriptor; } /* Used for parse_texi_text. STRING should be a UTF-8 buffer. */ size_t parse_text (const char *string, int line_nr) { size_t document_descriptor = initialize_parsing (ct_base); input_push_text (strdup (string), line_nr, 0, 0); parse_texi_document (); return document_descriptor; } /* Set DOCUMENT_DESCRIPTOR to the value corresponding to the tree obtained by parsing the Texinfo code in STRING. STRING should be a UTF-8 buffer. Used for parse_texi_line. */ size_t parse_string (const char *string, int line_nr) { ELEMENT *root_elt; size_t document_descriptor = initialize_parsing (ct_line); root_elt = new_element (ET_root_line); input_push_text (strdup (string), line_nr, 0, 0); parse_texi (root_elt, root_elt); return document_descriptor; } /* Used for parse_texi_piece. STRING should be a UTF-8 buffer. */ size_t parse_piece (const char *string, int line_nr) { size_t document_descriptor = initialize_parsing (ct_base); ELEMENT *before_node_section, *document_root; before_node_section = setup_document_root_and_before_node_section (); document_root = before_node_section->parent; input_push_text (strdup (string), line_nr, 0, 0); parse_texi (document_root, before_node_section); return document_descriptor; } void parser_conf_reset_values (void) { wipe_values (&global_parser_conf.values); } void parser_conf_add_value (const char *name, const char *value) { store_value (&global_parser_conf.values, name, value); }