File indexing completed on 2024-05-12 04:33:36

0001 /*
0002     SPDX-FileCopyrightText: 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr
0003     SPDX-License-Identifier: X11
0004 
0005     This file is part of the __SyncTeX__ package.
0006 
0007     [//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017)
0008     [//]: # (Version: 1.19)
0009 
0010     See `synctex_parser_readme.md` for more details
0011 */
0012 
0013 #include "synctex_parser.h"
0014 #include "synctex_parser_utils.h"
0015 
0016 #ifndef __SYNCTEX_PARSER_PRIVATE__
0017 #define __SYNCTEX_PARSER_PRIVATE__
0018 
0019 #ifdef __cplusplus
0020 extern "C" {
0021 #endif
0022 /*  Reminder that the argument must not be NULL */
0023 typedef synctex_node_p synctex_non_null_node_p;
0024 
0025 /*  Each node of the tree, except the scanner itself belongs to a class.
0026  *  The class object is just a struct declaring the owning scanner
0027  *  This is a pointer to the scanner as root of the tree.
0028  *  The type is used to identify the kind of node.
0029  *  The class declares pointers to a creator and a destructor method.
0030  *  The log and display fields are used to log and display the node.
0031  *  display will also display the child, sibling and parent sibling.
0032  *  parent, child and sibling are used to navigate the tree,
0033  *  from TeX box hierarchy point of view.
0034  *  The friend field points to a method which allows to navigate from friend to friend.
0035  *  A friend is a node with very close tag and line numbers.
0036  *  Finally, the info field point to a method giving the private node info offset.
0037  */
0038 
0039 /**
0040  *  These are the masks for the synctex node types.
0041  *  int's are 32 bits at least.
0042  */
0043 enum { synctex_shift_root, synctex_shift_no_root, synctex_shift_void, synctex_shift_no_void, synctex_shift_box, synctex_shift_no_box, synctex_shift_proxy, synctex_shift_no_proxy, synctex_shift_h, synctex_shift_v };
0044 enum {
0045     synctex_mask_root = 1,
0046     synctex_mask_no_root = synctex_mask_root << 1,
0047     synctex_mask_void = synctex_mask_no_root << 1,
0048     synctex_mask_no_void = synctex_mask_void << 1,
0049     synctex_mask_box = synctex_mask_no_void << 1,
0050     synctex_mask_no_box = synctex_mask_box << 1,
0051     synctex_mask_proxy = synctex_mask_no_box << 1,
0052     synctex_mask_no_proxy = synctex_mask_proxy << 1,
0053     synctex_mask_h = synctex_mask_no_proxy << 1,
0054     synctex_mask_v = synctex_mask_h << 1,
0055 };
0056 enum { synctex_mask_non_void_hbox = synctex_mask_no_void | synctex_mask_box | synctex_mask_h, synctex_mask_non_void_vbox = synctex_mask_no_void | synctex_mask_box | synctex_mask_v };
0057 typedef enum {
0058     synctex_node_mask_sf = synctex_mask_root | synctex_mask_no_void | synctex_mask_no_box | synctex_mask_no_proxy,
0059     synctex_node_mask_vbox = synctex_mask_no_root | synctex_mask_no_void | synctex_mask_box | synctex_mask_no_proxy | synctex_mask_v,
0060     synctex_node_mask_hbox = synctex_mask_no_root | synctex_mask_no_void | synctex_mask_box | synctex_mask_no_proxy | synctex_mask_h,
0061     synctex_node_mask_void_vbox = synctex_mask_no_root | synctex_mask_void | synctex_mask_box | synctex_mask_no_proxy | synctex_mask_v,
0062     synctex_node_mask_void_hbox = synctex_mask_no_root | synctex_mask_void | synctex_mask_box | synctex_mask_no_proxy | synctex_mask_h,
0063     synctex_node_mask_vbox_proxy = synctex_mask_no_root | synctex_mask_no_void | synctex_mask_box | synctex_mask_proxy | synctex_mask_v,
0064     synctex_node_mask_hbox_proxy = synctex_mask_no_root | synctex_mask_no_void | synctex_mask_box | synctex_mask_proxy | synctex_mask_h,
0065     synctex_node_mask_nvnn = synctex_mask_no_root | synctex_mask_void | synctex_mask_no_box | synctex_mask_no_proxy,
0066     synctex_node_mask_input = synctex_mask_root | synctex_mask_void | synctex_mask_no_box | synctex_mask_no_proxy,
0067     synctex_node_mask_proxy = synctex_mask_no_root | synctex_mask_void | synctex_mask_no_box | synctex_mask_proxy
0068 } synctex_node_mask_t;
0069 
0070 enum {
0071     /* input */
0072     synctex_tree_sibling_idx = 0,
0073     synctex_tree_s_input_max = 1,
0074     /* All */
0075     synctex_tree_s_parent_idx = 1,
0076     synctex_tree_sp_child_idx = 2,
0077     synctex_tree_spc_friend_idx = 3,
0078     synctex_tree_spcf_last_idx = 4,
0079     synctex_tree_spcfl_vbox_max = 5,
0080     /* hbox supplement */
0081     synctex_tree_spcfl_next_hbox_idx = 5,
0082     synctex_tree_spcfln_hbox_max = 6,
0083     /* hbox proxy supplement */
0084     synctex_tree_spcfln_target_idx = 6,
0085     synctex_tree_spcflnt_proxy_hbox_max = 7,
0086     /* vbox proxy supplement */
0087     synctex_tree_spcfl_target_idx = 5,
0088     synctex_tree_spcflt_proxy_vbox_max = 6,
0089     /*  spf supplement*/
0090     synctex_tree_sp_friend_idx = 2,
0091     synctex_tree_spf_max = 3,
0092     /*  box boundary supplement */
0093     synctex_tree_spf_arg_sibling_idx = 3,
0094     synctex_tree_spfa_max = 4,
0095     /*  proxy supplement */
0096     synctex_tree_spf_target_idx = 3,
0097     synctex_tree_spft_proxy_max = 4,
0098     /*  last proxy supplement */
0099     synctex_tree_spfa_target_idx = 4,
0100     synctex_tree_spfat_proxy_last_max = 5,
0101     /* sheet supplement */
0102     synctex_tree_s_child_idx = 1,
0103     synctex_tree_sc_next_hbox_idx = 2,
0104     synctex_tree_scn_sheet_max = 3,
0105     /* form supplement */
0106     synctex_tree_sc_target_idx = 2,
0107     synctex_tree_sct_form_max = 3,
0108     /* spct */
0109     synctex_tree_spc_target_idx = 3,
0110     synctex_tree_spct_handle_max = 4,
0111 };
0112 
0113 enum {
0114     /* input */
0115     synctex_data_input_tag_idx = 0,
0116     synctex_data_input_line_idx = 1,
0117     synctex_data_input_name_idx = 2,
0118     synctex_data_input_tln_max = 3,
0119     /* sheet */
0120     synctex_data_sheet_page_idx = 0,
0121     synctex_data_p_sheet_max = 1,
0122     /* form */
0123     synctex_data_form_tag_idx = 0,
0124     synctex_data_t_form_max = 1,
0125     /* tlchv */
0126     synctex_data_tag_idx = 0,
0127     synctex_data_line_idx = 1,
0128     synctex_data_column_idx = 2,
0129     synctex_data_h_idx = 3,
0130     synctex_data_v_idx = 4,
0131     synctex_data_tlchv_max = 5,
0132     /* tlchvw */
0133     synctex_data_width_idx = 5,
0134     synctex_data_tlchvw_max = 6,
0135     /* box */
0136     synctex_data_height_idx = 6,
0137     synctex_data_depth_idx = 7,
0138     synctex_data_box_max = 8,
0139     /* hbox supplement */
0140     synctex_data_mean_line_idx = 8,
0141     synctex_data_weight_idx = 9,
0142     synctex_data_h_V_idx = 10,
0143     synctex_data_v_V_idx = 11,
0144     synctex_data_width_V_idx = 12,
0145     synctex_data_height_V_idx = 13,
0146     synctex_data_depth_V_idx = 14,
0147     synctex_data_hbox_max = 15,
0148     /* ref */
0149     synctex_data_ref_tag_idx = 0,
0150     synctex_data_ref_h_idx = 1,
0151     synctex_data_ref_v_idx = 2,
0152     synctex_data_ref_thv_max = 3,
0153     /* proxy */
0154     synctex_data_proxy_h_idx = 0,
0155     synctex_data_proxy_v_idx = 1,
0156     synctex_data_proxy_hv_max = 2,
0157 };
0158 
0159 /*  each synctex node has a class */
0160 typedef struct synctex_class_t synctex_class_s;
0161 typedef synctex_class_s *synctex_class_p;
0162 
0163 /*  synctex_node_p is a pointer to a node
0164  *  synctex_node_s is the target of the synctex_node_p pointer
0165  *  It is a pseudo object oriented program.
0166  *  class is a pointer to the class object the node belongs to.
0167  *  implementation is meant to contain the private data of the node
0168  *  basically, there are 2 kinds of information: navigation information and
0169  *  synctex information. Both will depend on the type of the node,
0170  *  thus different nodes will have different private data.
0171  *  There is no inheritancy overhead.
0172  */
0173 typedef union {
0174     synctex_node_p as_node;
0175     int as_integer;
0176     char *as_string;
0177     void *as_pointer;
0178 } synctex_data_u;
0179 typedef synctex_data_u *synctex_data_p;
0180 
0181 #if defined(SYNCTEX_USE_CHARINDEX)
0182 typedef unsigned int synctex_charindex_t;
0183 synctex_charindex_t synctex_node_charindex(synctex_node_p node);
0184 typedef synctex_charindex_t synctex_lineindex_t;
0185 synctex_lineindex_t synctex_node_lineindex(synctex_node_p node);
0186 synctex_node_p synctex_scanner_handle(synctex_scanner_p scanner);
0187 #define SYNCTEX_DECLARE_CHARINDEX                                                                                                                                                                                                              \
0188     synctex_charindex_t char_index;                                                                                                                                                                                                            \
0189     synctex_lineindex_t line_index;
0190 #define SYNCTEX_DECLARE_CHAR_OFFSET synctex_charindex_t charindex_offset;
0191 #else
0192 #define SYNCTEX_DECLARE_CHARINDEX
0193 #define SYNCTEX_DECLARE_CHAR_OFFSET
0194 #endif
0195 struct synctex_node_t {
0196     SYNCTEX_DECLARE_CHARINDEX
0197     synctex_class_p class;
0198 #ifdef DEBUG
0199     synctex_data_u data[22];
0200 #else
0201     synctex_data_u data[1];
0202 #endif
0203 };
0204 
0205 typedef synctex_node_p *synctex_node_r;
0206 
0207 typedef struct {
0208     int h;
0209     int v;
0210 } synctex_point_s;
0211 
0212 typedef synctex_point_s *synctex_point_p;
0213 
0214 typedef struct {
0215     synctex_point_s min; /* top left */
0216     synctex_point_s max; /* bottom right */
0217 } synctex_box_s;
0218 
0219 typedef synctex_box_s *synctex_box_p;
0220 /**
0221  *  These are the types of the synctex nodes.
0222  *  No need to use them but the compiler needs them here.
0223  *  There are 3 kinds of nodes.
0224  *  - primary nodes
0225  *  - proxies
0226  *  - handles
0227  *  Primary nodes are created at parse time
0228  *  of the synctex file.
0229  *  Proxies are used to support pdf forms.
0230  *  The ref primary nodes are replaced by a tree
0231  *  of proxy nodes which duplicate the tree of primary
0232  *  nodes available in the referred form.
0233  *  Roughly speaking, the primary nodes of the form
0234  *  know what to display, the proxy nodes know where.
0235  *  Handles are used in queries. They point to either
0236  *  primary nodes or proxies.
0237  */
0238 typedef enum {
0239     synctex_node_type_none = 0,
0240     synctex_node_type_input,
0241     synctex_node_type_sheet,
0242     synctex_node_type_form,
0243     synctex_node_type_ref,
0244     synctex_node_type_vbox,
0245     synctex_node_type_void_vbox,
0246     synctex_node_type_hbox,
0247     synctex_node_type_void_hbox,
0248     synctex_node_type_kern,
0249     synctex_node_type_glue,
0250     synctex_node_type_rule,
0251     synctex_node_type_math,
0252     synctex_node_type_boundary,
0253     synctex_node_type_box_bdry,
0254     synctex_node_type_proxy,
0255     synctex_node_type_proxy_last,
0256     synctex_node_type_proxy_vbox,
0257     synctex_node_type_proxy_hbox,
0258     synctex_node_type_handle,
0259     synctex_node_number_of_types
0260 } synctex_node_type_t;
0261 /*  synctex_node_type gives the type of a given node,
0262  *  synctex_node_isa gives the same information as a human readable text. */
0263 synctex_node_type_t synctex_node_type(synctex_node_p node);
0264 const char *synctex_node_isa(synctex_node_p node);
0265 
0266 synctex_node_type_t synctex_node_target_type(synctex_node_p node);
0267 
0268 synctex_node_type_t synctex_node_type(synctex_node_p node);
0269 const char *synctex_node_isa(synctex_node_p node);
0270 
0271 void synctex_node_log(synctex_node_p node);
0272 void synctex_node_display(synctex_node_p node);
0273 
0274 /*  Given a node, access to the location in the synctex file where it is defined.
0275  */
0276 
0277 int synctex_node_form_tag(synctex_node_p node);
0278 
0279 int synctex_node_mean_line(synctex_node_p node);
0280 int synctex_node_weight(synctex_node_p node);
0281 int synctex_node_child_count(synctex_node_p node);
0282 
0283 int synctex_node_h(synctex_node_p node);
0284 int synctex_node_v(synctex_node_p node);
0285 int synctex_node_width(synctex_node_p node);
0286 
0287 int synctex_node_box_h(synctex_node_p node);
0288 int synctex_node_box_v(synctex_node_p node);
0289 int synctex_node_box_width(synctex_node_p node);
0290 int synctex_node_box_height(synctex_node_p node);
0291 int synctex_node_box_depth(synctex_node_p node);
0292 
0293 int synctex_node_hbox_h(synctex_node_p node);
0294 int synctex_node_hbox_v(synctex_node_p node);
0295 int synctex_node_hbox_width(synctex_node_p node);
0296 int synctex_node_hbox_height(synctex_node_p node);
0297 int synctex_node_hbox_depth(synctex_node_p node);
0298 
0299 synctex_scanner_p synctex_scanner_new();
0300 synctex_node_p synctex_node_new(synctex_scanner_p scanner, synctex_node_type_t type);
0301 
0302 /**
0303  *  Scanner display switcher getter.
0304  *  If the switcher is 0, synctex_node_display is disabled.
0305  *  If the switcher is <0, synctex_node_display has no limit.
0306  *  If the switcher is >0, only the first switcher (as number) nodes are displayed.
0307  *  - parameter: a scanner
0308  *  - returns: an integer
0309  */
0310 int synctex_scanner_display_switcher(synctex_scanner_p scanR);
0311 void synctex_scanner_set_display_switcher(synctex_scanner_p scanR, int switcher);
0312 
0313 /**
0314  *  Iterator is the structure used to traverse
0315  *  the answer to client queries.
0316  *  First answers are the best matches, according
0317  *  to criteria explained below.
0318  *  Next answers are not ordered.
0319  *  Objects are handles to nodes in the synctex node tree starting at scanner.
0320  */
0321 typedef struct synctex_iterator_t synctex_iterator_s;
0322 typedef synctex_iterator_s *synctex_iterator_p;
0323 
0324 /**
0325  *  Designated creator for a display query, id est,
0326  *  forward navigation from source to output.
0327  *  Returns NULL if the query has no answer.
0328  *  Code example:
0329  *      synctex_iterator_p iterator = NULL;
0330  *      if ((iterator = synctex_iterator_new_display(...)) {
0331  *      synctex_node_p node = NULL;
0332  *      while((node = synctex_iterator_next_result(iterator))) {
0333  *          do something with node...
0334  *      }
0335  */
0336 synctex_iterator_p synctex_iterator_new_display(synctex_scanner_p scanner, const char *name, int line, int column, int page_hint);
0337 /**
0338  *  Designated creator for an  edit query, id est,
0339  *  backward navigation from output to source.
0340  *  Code example:
0341  *      synctex_iterator_p iterator = NULL;
0342  *      if ((iterator = synctex_iterator_new_edit(...)) {
0343  *      synctex_node_p node = NULL;
0344  *      while((node = synctex_iterator_next_result(iterator))) {
0345  *          do something with node...
0346  *      }
0347  */
0348 synctex_iterator_p synctex_iterator_new_edit(synctex_scanner_p scanner, int page, float h, float v);
0349 /**
0350  *  Free all the resources.
0351  *  - argument iterator: the object to free...
0352  *  You should free the iterator before the scanner
0353  *  owning the nodes it iterates with.
0354  */
0355 void synctex_iterator_free(synctex_iterator_p iterator);
0356 /**
0357  *  Whether the iterator actually points to an object.
0358  *  - argument iterator: the object to iterate on...
0359  */
0360 synctex_bool_t synctex_iterator_has_next(synctex_iterator_p iterator);
0361 /**
0362  *  Returns the pointed object and advance the cursor
0363  *  to the next object. Returns NULL and does nothing
0364  *  if the end has already been reached.
0365  *  - argument iterator: the object to iterate on...
0366  */
0367 synctex_node_p synctex_iterator_next_result(synctex_iterator_p iterator);
0368 /**
0369  *  Reset the cursor position to the first result.
0370  *  - argument iterator: the object to iterate on...
0371  */
0372 int synctex_iterator_reset(synctex_iterator_p iterator);
0373 /**
0374  *  The number of objects left for traversal.
0375  *  - argument iterator: the object to iterate on...
0376  */
0377 int synctex_iterator_count(synctex_iterator_p iterator);
0378 
0379 /**
0380  *  The target of the node, either a handle or a proxy.
0381  */
0382 synctex_node_p synctex_node_target(synctex_node_p node);
0383 
0384 #ifndef SYNCTEX_NO_UPDATER
0385 /*  The main synctex updater object.
0386  *  This object is used to append information to the synctex file.
0387  *  Its implementation is considered private.
0388  *  It is used by the synctex command line tool to take into account modifications
0389  *  that could occur while postprocessing files by dvipdf like filters.
0390  */
0391 typedef struct synctex_updater_t synctex_updater_s;
0392 typedef synctex_updater_s *synctex_updater_p;
0393 
0394 /*  Designated initializer.
0395  *  Once you are done with your whole job,
0396  *  free the updater */
0397 synctex_updater_p synctex_updater_new_with_output_file(const char *output, const char *directory);
0398 
0399 /*  Use the next functions to append records to the synctex file,
0400  *  no consistency tests made on the arguments */
0401 void synctex_updater_append_magnification(synctex_updater_p updater, char *magnification);
0402 void synctex_updater_append_x_offset(synctex_updater_p updater, char *x_offset);
0403 void synctex_updater_append_y_offset(synctex_updater_p updater, char *y_offset);
0404 
0405 /*  You MUST free the updater, once everything is properly appended */
0406 void synctex_updater_free(synctex_updater_p updater);
0407 #endif
0408 
0409 #if defined(SYNCTEX_DEBUG)
0410 #include "assert.h"
0411 #define SYNCTEX_ASSERT assert
0412 #else
0413 #define SYNCTEX_ASSERT(UNUSED)
0414 #endif
0415 
0416 #if defined(SYNCTEX_TESTING)
0417 #warning TESTING IS PROHIBITED
0418 #if __clang__
0419 #define __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wformat-extra-args\"")
0420 
0421 #define __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS _Pragma("clang diagnostic pop")
0422 #else
0423 #define __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS
0424 #define __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS
0425 #endif
0426 
0427 #define SYNCTEX_TEST_BODY(counter, condition, desc, ...)                                                                                                                                                                                       \
0428     do {                                                                                                                                                                                                                                       \
0429         __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS                                                                                                                                                                                                    \
0430         if (!(condition)) {                                                                                                                                                                                                                    \
0431             ++counter;                                                                                                                                                                                                                         \
0432             printf("**** Test failed: %s\nfile %s\nfunction %s\nline %i\n", #condition, __FILE__, __FUNCTION__, __LINE__);                                                                                                                     \
0433             printf((desc), ##__VA_ARGS__);                                                                                                                                                                                                     \
0434         }                                                                                                                                                                                                                                      \
0435         __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS                                                                                                                                                                                                     \
0436     } while (0)
0437 
0438 #define SYNCTEX_TEST_PARAMETER(counter, condition) SYNCTEX_TEST_BODY(counter, (condition), "Invalid parameter not satisfying: %s", #condition)
0439 
0440 int synctex_test_input(synctex_scanner_p scanner);
0441 int synctex_test_proxy(synctex_scanner_p scanner);
0442 int synctex_test_tree(synctex_scanner_p scanner);
0443 int synctex_test_page(synctex_scanner_p scanner);
0444 int synctex_test_handle(synctex_scanner_p scanner);
0445 int synctex_test_display_query(synctex_scanner_p scanner);
0446 int synctex_test_charindex();
0447 int synctex_test_sheet_1();
0448 int synctex_test_sheet_2();
0449 int synctex_test_sheet_3();
0450 int synctex_test_form();
0451 #endif
0452 
0453 #ifdef __cplusplus
0454 }
0455 #endif
0456 
0457 #endif