Update to synctex 1.19

Summary:
This should prevent crashes when reloading some synctex-enabled pdf
files created with newer versions of TeXLive. We also gain bugfixes,
features and improved accuracy from the last 6 years of synctex
development.

Procedure followed:
- svn co svn://tug.org/texlive/trunk/Build/source/texk/web2c/synctexdir
- Check out revision 45150
- Update files present in core/synctex/*
- Adapt Okular code to changes
- Review and drop or update/apply old patches using quilt
- Create missing patches for local synctex changes
- New patch: Omit warning message when opening non-synctex pdf
- Two new patches to fix more compiler warnings
- New patch: Plug multiple leaks and prevent a segfault

TODO for later:
- Move sync file detection code to Okular to never call into synctex C code for non-synctex files
- Evaluate feasibility of upstreaming all patches for TeXLive 2018 and using synctex as a library

BUG: 383915
FIXED-IN: 17.12.0

Test Plan:
- No crash in synctex on reloading empty.pdf from bugreport anymore.
- Shift-clicking on a word in a simple pdf opens Kate with the corresponding tex line.
- Forward and backward search in Kile seems to work.
- Works with synctex files from both TeXLive 2015 and 2017.
- PartTest::testForwardPDF still passes.
- No additional memory leaks in autotests and with basic synctex and non-synctex usage of Okular.

Reviewers: #okular, sander, #kile, aacid

Reviewed By: #okular, aacid

Subscribers: mludwig, aacid

Tags: #okular

Differential Revision: https://phabricator.kde.org/D7594
This commit is contained in:
Henrik Fehlauer 2017-08-29 00:29:46 +02:00
parent 9d4067059f
commit bd20e48c3c
27 changed files with 10338 additions and 4590 deletions

View file

@ -34,8 +34,8 @@ class PartTest
void testReload();
void testCanceledReload();
void testTOCReload();
void testFowardPDF();
void testFowardPDF_data();
void testForwardPDF();
void testForwardPDF_data();
void testGeneratorPreferences();
void testSelectText();
void testClickInternalLink();
@ -113,7 +113,7 @@ void PartTest::testTOCReload()
QCOMPARE(part.m_toc->expandedNodes().count(), 3);
}
void PartTest::testFowardPDF()
void PartTest::testForwardPDF()
{
QFETCH(QString, dir);
@ -161,7 +161,7 @@ void PartTest::testFowardPDF()
QCOMPARE(part.m_document->currentPage(), 1u);
}
void PartTest::testFowardPDF_data()
void PartTest::testForwardPDF_data()
{
QTest::addColumn<QString>("dir");

View file

@ -3020,12 +3020,12 @@ QVariant Document::metaData( const QString & key, const QVariant & option ) cons
if (!ok) line = -1;
// Use column == -1 for now.
if( synctex_display_query( d->m_synctex_scanner, QFile::encodeName(name).constData(), line, -1 ) > 0 )
if( synctex_display_query( d->m_synctex_scanner, QFile::encodeName(name).constData(), line, -1, 0 ) > 0 )
{
synctex_node_t node;
synctex_node_p node;
// For now use the first hit. Could possibly be made smarter
// in case there are multiple hits.
while( ( node = synctex_next_result( d->m_synctex_scanner ) ) )
while( ( node = synctex_scanner_next_result( d->m_synctex_scanner ) ) )
{
Okular::DocumentViewport viewport;
@ -4128,9 +4128,9 @@ const SourceReference * Document::dynamicSourceReference( int pageNr, double abs
if (synctex_edit_query(d->m_synctex_scanner, pageNr + 1, absX * 72. / dpi.width(), absY * 72. / dpi.height()) > 0)
{
synctex_node_t node;
synctex_node_p node;
// TODO what should we do if there is really more than one node?
while (( node = synctex_next_result( d->m_synctex_scanner ) ))
while (( node = synctex_scanner_next_result( d->m_synctex_scanner ) ))
{
int line = synctex_node_line(node);
int col = synctex_node_column(node);

View file

@ -280,7 +280,7 @@ class DocumentPrivate
QUndoStack *m_undoStack;
QDomNode m_prevPropsOfAnnotBeingModified;
synctex_scanner_t m_synctex_scanner;
synctex_scanner_p m_synctex_scanner;
// generator selection
static QVector<KPluginMetaData> availableGenerators();

View file

@ -1,12 +1,13 @@
Description: Disable SYNCTEX_INLINE on non-MSVC compilers.
It is misplaced in the code (before "static"), so it causes compiling errors.
Disable SYNCTEX_INLINE on non-MSVC compilers. It is misplaced
in the code (before "static"), so it causes compiling errors.
Author: Pino Toscano <pino@kde.org>
diff --git a/generators/poppler/synctex/synctex_parser.c b/generators/poppler/synctex/synctex_parser.c
index 0d3de08..53f462d 100644
--- a/generators/poppler/synctex/synctex_parser.c
+++ b/generators/poppler/synctex/synctex_parser.c
@@ -67,7 +67,7 @@ Thu Jun 19 09:39:21 UTC 2008
# if defined(_MSC_VER)
Index: synctex/synctex_parser.c
===================================================================
--- synctex.orig/synctex_parser.c
+++ synctex/synctex_parser.c
@@ -91,7 +91,7 @@
# if defined(_MSC_VER)
# define SYNCTEX_INLINE __inline
# else
-# define SYNCTEX_INLINE inline

View file

@ -1,42 +0,0 @@
diff --git a/generators/poppler/synctex/synctex_parser_utils.c b/generators/poppler/synctex/synctex_parser_utils.c
index 569f7e9..e85ca73 100644
--- a/generators/poppler/synctex/synctex_parser_utils.c
+++ b/generators/poppler/synctex/synctex_parser_utils.c
@@ -157,7 +157,7 @@ synctex_bool_t _synctex_is_equivalent_file_name(const char *lhs, const char *rhs
/* Remove the leading regex '(\./+)*' in both rhs and lhs */
lhs = synctex_ignore_leading_dot_slash(lhs);
rhs = synctex_ignore_leading_dot_slash(rhs);
-# if SYNCTEX_WINDOWS
+# ifdef SYNCTEX_WINDOWS
/* On Windows, filename should be compared case insensitive.
* The characters '/' and '\' are both valid path separators.
* There will be a very serious problem concerning UTF8 because
@@ -189,7 +189,7 @@ synctex_bool_t _synctex_path_is_absolute(const char * name) {
if(!strlen(name)) {
return synctex_NO;
}
-# if SYNCTEX_WINDOWS
+# ifdef SYNCTEX_WINDOWS
if(strlen(name)>2) {
return (name[1]==':' && SYNCTEX_IS_PATH_SEPARATOR(name[2]))?synctex_YES:synctex_NO;
}
diff --git a/generators/poppler/synctex/synctex_parser_utils.h b/generators/poppler/synctex/synctex_parser_utils.h
index e67f8f5..f0709e9 100644
--- a/generators/poppler/synctex/synctex_parser_utils.h
+++ b/generators/poppler/synctex/synctex_parser_utils.h
@@ -61,13 +61,13 @@ authorization from the copyright holder.
extern "C" {
#endif
-# if _WIN32
+# ifdef _WIN32
# define SYNCTEX_IS_PATH_SEPARATOR(c) ('/' == c || '\\' == c)
# else
# define SYNCTEX_IS_PATH_SEPARATOR(c) ('/' == c)
# endif
-# if _WIN32
+# ifdef _WIN32
# define SYNCTEX_IS_DOT(c) ('.' == c)
# else
# define SYNCTEX_IS_DOT(c) ('.' == c)

View file

@ -1,28 +1,67 @@
diff --git a/generators/poppler/synctex/synctex_parser_utils.h b/generators/poppler/synctex/synctex_parser_utils.h
index f0709e9..92184b8 100644
--- a/generators/poppler/synctex/synctex_parser_utils.h
+++ b/generators/poppler/synctex/synctex_parser_utils.h
@@ -72,7 +72,13 @@ extern "C" {
_synctex_error has a printf-like format, so use the proper gcc extensions
to check its arguments (doing nothing for other compilers)
Author: Pino Toscano <pino@kde.org>
Index: synctex/synctex_parser_utils.h
===================================================================
--- synctex.orig/synctex_parser_utils.h
+++ synctex/synctex_parser_utils.h
@@ -83,6 +83,12 @@ extern "C" {
# else
# define SYNCTEX_IS_DOT(c) ('.' == c)
# define SYNCTEX_ARE_PATH_CHARACTERS_EQUAL(left,right) (toupper(left) != toupper(right))
# endif
-
+
+# ifdef __GNUC__
+# define SYNCTEX_PRINTF_FORMAT(si, ftc) __attribute__ ((format (printf, si, ftc)))
+# else
+# define SYNCTEX_PRINTF_FORMAT(si, ftc)
+# endif
+
/* This custom malloc functions initializes to 0 the newly allocated memory.
* There is no bzero function on windows. */
void *_synctex_malloc(size_t size);
@@ -80,7 +86,7 @@ void *_synctex_malloc(size_t size);
@@ -95,8 +101,8 @@ void _synctex_free(void * ptr);
/* This is used to log some informational message to the standard error stream.
* On Windows, the stderr stream is not exposed and another method is used.
* The return value is the number of characters printed. */
-int _synctex_error(const char * reason,...);
+int _synctex_error(const char * reason,...) SYNCTEX_PRINTF_FORMAT(1, 2);
- int _synctex_error(const char * reason,...);
- int _synctex_debug(const char * reason,...);
+ int _synctex_error(const char * reason,...) SYNCTEX_PRINTF_FORMAT(1, 2);
+ int _synctex_debug(const char * reason,...) SYNCTEX_PRINTF_FORMAT(1, 2);
/* strip the last extension of the given string, this string is modified!
* This function depends on the OS because the path separator may differ.
Index: synctex/synctex_parser.c
===================================================================
--- synctex.orig/synctex_parser.c
+++ synctex/synctex_parser.c
@@ -8148,6 +8148,7 @@ struct synctex_updater_t {
int length; /* the number of chars appended */
};
+static int _synctex_updater_print(synctex_updater_p updater, const char * format, ...) SYNCTEX_PRINTF_FORMAT(2, 3);
static int _synctex_updater_print(synctex_updater_p updater, const char * format, ...) {
int result = 0;
if (updater) {
@@ -8184,6 +8185,7 @@ static int vasprintf(char **ret,
/**
* gzvprintf is not available until OSX 10.10
*/
+static int _synctex_updater_print_gz(synctex_updater_p updater, const char * format, ...) SYNCTEX_PRINTF_FORMAT(2, 3);
static int _synctex_updater_print_gz(synctex_updater_p updater, const char * format, ...) {
int result = 0;
if (updater) {
Index: synctex/synctex_parser_utils.c
===================================================================
--- synctex.orig/synctex_parser_utils.c
+++ synctex/synctex_parser_utils.c
@@ -87,7 +87,9 @@ void _synctex_free(void * ptr) {
# include <syslog.h>
#endif
-int _synctex_log(int level, const char * prompt, const char * reason, va_list arg;) {
+int _synctex_log(int level, const char * prompt, const char * reason, ...) SYNCTEX_PRINTF_FORMAT(3, 4);
+int _synctex_log(int level, const char * prompt, const char * reason, ...) {
+ va_list arg;
int result;
# ifdef SYNCTEX_RECENT_WINDOWS
{/* This code is contributed by William Blum.

View file

@ -1,13 +0,0 @@
diff --git a/generators/poppler/synctex/synctex_parser.c b/generators/poppler/synctex/synctex_parser.c
index 53f462d..588f350 100644
--- a/generators/poppler/synctex/synctex_parser.c
+++ b/generators/poppler/synctex/synctex_parser.c
@@ -1440,7 +1440,7 @@ next_character:
len = SYNCTEX_END - SYNCTEX_CUR;
if (current_size>UINT_MAX-len-1) {
/* We have reached the limit. */
- _synctex_error("limit reached (missing %i).",current_size-(UINT_MAX-len-1));
+ _synctex_error("limit reached (missing %lu).",current_size-(UINT_MAX-len-1));
return SYNCTEX_STATUS_ERROR;
}
new_size = current_size+len;

View file

@ -2,18 +2,19 @@ _vscprintf() is specific for MSVC; thus in _synctex_error(), for any other
compiler on Windows, use _vsnprintf() and grow the buffer until necessary.
Patch provided by Patrick Spendrin <ps_ml@gmx.de>.
diff --git a/generators/poppler/synctex/synctex_parser_utils.c b/generators/poppler/synctex/synctex_parser_utils.c
index e85ca73..ef1645e 100644
--- a/generators/poppler/synctex/synctex_parser_utils.c
+++ b/generators/poppler/synctex/synctex_parser_utils.c
@@ -90,8 +90,26 @@ int _synctex_error(const char * reason,...) {
Index: synctex/synctex_parser_utils.c
===================================================================
--- synctex.orig/synctex_parser_utils.c
+++ synctex/synctex_parser_utils.c
@@ -101,8 +101,26 @@ int _synctex_log(int level, const char *
char *buff;
size_t len;
OutputDebugStringA("SyncTeX ERROR: ");
OutputDebugStringA(prompt);
+# ifdef _MSC_VER
len = _vscprintf(reason, arg) + 1;
buff = (char*)malloc( len * sizeof(char) );
+#else /* MinGW */
+# else /* MinGW */
+ size_t buffersize = 1024;
+ size_t max_buffersize = 1024 * buffersize;
+ int result;
@ -29,7 +30,7 @@ index e85ca73..ef1645e 100644
+ free(buff);
+ return -1;
+ }
+#endif
result = vsprintf(buff, reason, arg) +strlen("SyncTeX ERROR: ");
+# endif
result = vsprintf(buff, reason, arg) +strlen(prompt);
OutputDebugStringA(buff);
OutputDebugStringA("\n");

View file

@ -1,21 +0,0 @@
Description: synctex_scanner_new_with_output_file: reset the io_mode to read before trying to read again
synctex_scanner_new_with_output_file() tries first to open the file in an
"unquoted mode"; if it fails, it tries again quoting the file name.
During the first attempt, the synctex_io_mode_t is passed as pointer and it
can be incremented, making the second attempt start from "rb" instead of "r".
The easiest solution is to reset the io_mode before doing the second open
attempt.
Author: Albert Astals Cid <aacid@kde.org>
diff --git a/generators/poppler/synctex/synctex_parser.c b/generators/poppler/synctex/synctex_parser.c
index 588f350..c8f61bb 100644
--- a/generators/poppler/synctex/synctex_parser.c
+++ b/generators/poppler/synctex/synctex_parser.c
@@ -2584,6 +2584,8 @@ synctex_scanner_t synctex_scanner_new_with_output_file(const char * output, cons
}
/* now open the synctex file */
if (_synctex_open(output,build_directory,&synctex,&file,synctex_ADD_QUOTES,&io_mode) || !file) {
+ /* reset the io_mode to the default, ie read */
+ io_mode = 0;
if (_synctex_open(output,build_directory,&synctex,&file,synctex_DONT_ADD_QUOTES,&io_mode) || !file) {
return NULL;
}

View file

@ -1,27 +1,33 @@
diff --git a/generators/poppler/synctex/synctex_parser.c b/generators/poppler/synctex/synctex_parser.c
index c8f61bb..8244f27 100644
--- a/generators/poppler/synctex/synctex_parser.c
+++ b/generators/poppler/synctex/synctex_parser.c
@@ -3395,11 +3395,11 @@ int synctex_display_query(synctex_scanner_t scanner,const char * name,int line,i
}
start_ref += 1;
SYNCTEX_END = (char *)start_ref;
- SYNCTEX_CUR = NULL;// added on behalf of Jose Alliste
- return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);// added on behalf Jan Sundermeyer
+ SYNCTEX_CUR = NULL;/* added on behalf of Jose Alliste */
+ return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t);/* added on behalf Jan Sundermeyer */
Fix cpp comments
Author: Albert Astals Cid <aacid@kde.org>
Index: synctex/synctex_parser.c
===================================================================
--- synctex.orig/synctex_parser.c
+++ synctex/synctex_parser.c
@@ -6048,7 +6048,7 @@ static int _synctex_scanner_get_tag(sync
}
SYNCTEX_CUR = NULL;
- // return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t); removed on behalf Jan Sundermeyer
+ /* return (SYNCTEX_END-SYNCTEX_START)/sizeof(synctex_node_t); removed on behalf Jan Sundermeyer */
}
# if defined(__SYNCTEX_STRONG_DISPLAY_QUERY__)
break;
diff --git a/generators/poppler/synctex/synctex_parser_utils.c b/generators/poppler/synctex/synctex_parser_utils.c
index ef1645e..3be45b7 100644
--- a/generators/poppler/synctex/synctex_parser_utils.c
+++ b/generators/poppler/synctex/synctex_parser_utils.c
@@ -492,6 +492,6 @@ int _synctex_get_name(const char * output, const char * build_directory, char **
} while((input = __synctex_tree_sibling(input)));
}
- // 2011 version
+ /* 2011 version */
name = _synctex_base_name(name);
if ((input = scanner->input)) {
do {
@@ -6058,7 +6058,7 @@ static int _synctex_scanner_get_tag(sync
if (_synctex_is_equivalent_file_name(name,_synctex_base_name(_synctex_data_name(other_input)))
&& (strlen(_synctex_data_name(input))!=strlen(_synctex_data_name(other_input))
|| strncmp(_synctex_data_name(other_input),_synctex_data_name(input),strlen(_synctex_data_name(input))))) {
- // There is a second possible candidate
+ /* There is a second possible candidate */
return 0;
}
}
Index: synctex/synctex_parser_utils.c
===================================================================
--- synctex.orig/synctex_parser_utils.c
+++ synctex/synctex_parser_utils.c
@@ -583,6 +583,6 @@ int _synctex_get_name(const char * outpu
const char * _synctex_get_io_mode_name(synctex_io_mode_t io_mode) {
static const char * synctex_io_modes[4] = {"r","rb","a","ab"};

View file

@ -1,22 +0,0 @@
diff --git a/generators/poppler/synctex/synctex_parser_utils.c b/generators/poppler/synctex/synctex_parser_utils.c
index 3be45b7..3dd764f 100644
--- a/generators/poppler/synctex/synctex_parser_utils.c
+++ b/generators/poppler/synctex/synctex_parser_utils.c
@@ -199,7 +199,16 @@ next_character:
++rhs;
goto next_character;
# else
- return 0 == strcmp(lhs,rhs)?synctex_YES:synctex_NO;
+ if (lhs[0] == '/' && rhs[0] == '/') { /* for absolute paths compare the real paths */
+ char *lhsreal = realpath(lhs, 0);
+ char *rhsreal = realpath(rhs, 0);
+ synctex_bool_t result = lhsreal && rhsreal && 0 == strcmp(lhsreal,rhsreal)?synctex_YES:synctex_NO;
+ free (lhsreal);
+ free (rhsreal);
+ return result;
+ } else {
+ return 0 == strcmp(lhs,rhs)?synctex_YES:synctex_NO;
+ }
# endif
}

View file

@ -0,0 +1,17 @@
Fix some typos found by Krazy2
Author: Yuri Chornoivan <yurchor@ukr.net>
Original commit: 3b73357
Index: synctex/synctex_parser_utils.c
===================================================================
--- synctex.orig/synctex_parser_utils.c
+++ synctex/synctex_parser_utils.c
@@ -406,7 +406,7 @@ char * _synctex_merge_strings(const char
/* The purpose of _synctex_get_name is to find the name of the synctex file.
* There is a list of possible filenames from which we return the most recent one and try to remove all the others.
- * With two runs of pdftex or xetex we are sure the the synctex file is really the most appropriate.
+ * With two runs of pdftex or xetex we are sure the synctex file is really the most appropriate.
*/
int _synctex_get_name(const char * output, const char * build_directory, char ** synctex_name_ref, synctex_io_mode_t * io_mode_ref)
{

View file

@ -0,0 +1,49 @@
Fix low hanging unused parameters warnings
Author: Martin T. H. Sandsmark <martin.sandsmark@kde.org>
Original commit: d5bdca6
Index: synctex/synctex_parser.c
===================================================================
--- synctex.orig/synctex_parser.c
+++ synctex/synctex_parser.c
@@ -198,9 +198,7 @@ typedef struct synctex_tlcpector_t {
} synctex_tlcpector_s;
typedef const synctex_tlcpector_s * synctex_tlcpector_p;
static int _synctex_int_none(synctex_node_p node) {
-# ifdef __DARWIN_UNIX03
-# pragma unused(node)
-# endif
+ (void)node; /* unused */
return 0;
}
static const synctex_tlcpector_s synctex_tlcpector_none = {
@@ -234,9 +232,7 @@ typedef struct synctex_vispector_t {
synctex_float_getter_f depth;
} synctex_vispector_s;
static float _synctex_float_none(synctex_node_p node) {
-# ifdef __DARWIN_UNIX03
-# pragma unused(node)
-# endif
+ (void)node; /* unused */
return 0;
}
static const synctex_vispector_s synctex_vispector_none = {
@@ -7206,9 +7202,7 @@ static synctex_node_p _synctex_display_q
return first_handle;
}
synctex_iterator_p synctex_iterator_new_display(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint) {
-# ifdef __DARWIN_UNIX03
-# pragma unused(column)
-# endif
+ (void)column; /* unused */
if (scanner) {
int tag = synctex_scanner_get_tag(scanner,name);/* parse if necessary */
int max_line = 0;
@@ -7977,6 +7971,7 @@ SYNCTEX_INLINE static synctex_nd_lr_s __
}
#endif
SYNCTEX_INLINE static synctex_nd_lr_s __synctex_eq_get_closest_children_in_vbox_v2(synctex_point_p hitP, synctex_node_p nodeP) {
+ (void)nodeP; /* unused */
synctex_nd_lr_s nds = {SYNCTEX_ND_0,SYNCTEX_ND_0};
synctex_nd_s nd = SYNCTEX_ND_0;
if ((nd.node = synctex_node_child(nd.node))) {

View file

@ -0,0 +1,17 @@
Omit warning message when opening non-synctex pdf
Author: Henrik Fehlauer <rkflx@lab12.net>
Index: synctex/synctex_parser.c
===================================================================
--- synctex.orig/synctex_parser.c
+++ synctex/synctex_parser.c
@@ -5838,7 +5838,9 @@ synctex_scanner_p synctex_scanner_new_wi
if ((scanner->reader = synctex_reader_init_with_output_file(scanner->reader, output, build_directory))) {
return parse? synctex_scanner_parse(scanner):scanner;
}
+#if defined(SYNCTEX_DEBUG)
_synctex_error("No file?");
+#endif
return NULL;
}

View file

@ -0,0 +1,326 @@
Fix compiler warnings for -Wundef
Author: Henrik Fehlauer <rkflx@lab12.net>
Index: synctex/synctex_parser.c
===================================================================
--- synctex.orig/synctex_parser.c
+++ synctex/synctex_parser.c
@@ -362,7 +362,7 @@ __synctex_scanner_register_handle_to(NOD
# pragma mark Tree SETGET
# endif
-#if SYNCTEX_DEBUG > 1000
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG > 1000
#define SYNCTEX_PARAMETER_ASSERT(WHAT) \
do { \
if (!(WHAT)) { \
@@ -459,11 +459,11 @@ DEFINE_SYNCTEX_TREE_GETSET(next_hbox)
DEFINE_SYNCTEX_TREE_GETSET(arg_sibling)
DEFINE_SYNCTEX_TREE_GETSET(target)
-#if SYNCTEX_DEBUG>1000
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>1000
# undef SYNCTEX_USE_NODE_COUNT
# define SYNCTEX_USE_NODE_COUNT 1
#endif
-#if SYNCTEX_USE_NODE_COUNT>0
+#if defined SYNCTEX_USE_NODE_COUNT && SYNCTEX_USE_NODE_COUNT>0
# define SYNCTEX_DECLARE_NODE_COUNT int node_count;
# define SYNCTEX_INIT_NODE_COUNT \
do { node_count = 0; } while(synctex_NO)
@@ -472,7 +472,7 @@ DEFINE_SYNCTEX_TREE_GETSET(target)
# define SYNCTEX_INIT_NODE_COUNT
#endif
-#if SYNCTEX_USE_NODE_COUNT>10
+#if defined SYNCTEX_USE_NODE_COUNT && SYNCTEX_USE_NODE_COUNT>10
# define SYNCTEX_DID_NEW(N) _synctex_did_new(N)
# define SYNCTEX_WILL_FREE(N) _synctex_will_free(N)
#else
@@ -865,7 +865,7 @@ SYNCTEX_INLINE static void __synctex_sca
node->class->scanner->handle = NNN;
}
#endif
-#if SYNCTEX_USE_NODE_COUNT>10
+#if defined SYNCTEX_USE_NODE_COUNT && SYNCTEX_USE_NODE_COUNT>10
SYNCTEX_INLINE static void _synctex_did_new(synctex_node_p node) {
printf("NODE CREATED # %i, %s, %p\n",
(node->class->scanner->node_count)++,
@@ -2516,7 +2516,7 @@ SYNCTEX_INLINE static synctex_nns_s _syn
}
static char * _synctex_node_abstract(synctex_node_p node);
SYNCTEX_INLINE static synctex_node_p synctex_tree_set_friend(synctex_node_p node,synctex_node_p new_friend) {
-#if SYNCTEX_DEBUG
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG
synctex_node_p F = new_friend;
while (F) {
if (node == F) {
@@ -2545,7 +2545,7 @@ SYNCTEX_INLINE static synctex_node_p __s
i = i%(node->class->scanner->number_of_lists);
old = synctex_tree_set_friend(node,(node->class->scanner->lists_of_friends)[i]);
(node->class->scanner->lists_of_friends)[i] = node;
-#if SYNCTEX_DEBUG>500
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>500
printf("tl(%i)=>",i);
synctex_node_log(node);
if (synctex_node_parent_form(node)) {
@@ -4186,7 +4186,7 @@ static synctex_ns_s __synctex_parse_new_
/* Prepend this input node to the input linked list of the scanner */
__synctex_tree_set_sibling(input,scanner->input);/* input has no parent */
scanner->input = input;
-# if SYNCTEX_VERBOSE
+# ifdef SYNCTEX_VERBOSE
synctex_node_log(input);
# endif
return (synctex_ns_s){input,_synctex_next_line(scanner)};/* read the line termination character, if any */
@@ -5083,10 +5083,10 @@ content_loop:
*/
/* forms are everywhere */
ns = SYNCTEX_NS_NULL;
-#if SYNCTEX_VERBOSE
+#ifdef SYNCTEX_VERBOSE
synctex_scanner_set_display_switcher(scanner,-1);
printf("NEW CONTENT LOOP\n");
-#if SYNCTEX_DEBUG>500
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>500
synctex_node_display(sheet);
#endif
#endif
@@ -5106,7 +5106,7 @@ content_loop:
}
parent = ns.node;
child = _synctex_tree_last(parent);
-# if SYNCTEX_VERBOSE
+# ifdef SYNCTEX_VERBOSE
synctex_node_log(parent);
# endif
input.node = _synctex_input_register_line(input.node,parent);
@@ -5124,7 +5124,7 @@ content_loop:
}
child = parent;
parent = _synctex_tree_parent(child);
-# if SYNCTEX_VERBOSE
+# ifdef SYNCTEX_VERBOSE
synctex_node_log(child);
# endif
if (_synctex_next_line(scanner)<SYNCTEX_STATUS_OK) {
@@ -5166,7 +5166,7 @@ content_loop:
} else {
_synctex_error("Can't create box bdry record.");
}
-# if SYNCTEX_VERBOSE
+# ifdef SYNCTEX_VERBOSE
synctex_node_log(parent);
# endif
input.node = _synctex_input_register_line(input.node,parent);
@@ -5238,7 +5238,7 @@ content_loop:
child = parent;
parent = _synctex_tree_parent(child);
_synctex_make_hbox_contain_box(parent,_synctex_data_box_V(child));
-# if SYNCTEX_VERBOSE
+# ifdef SYNCTEX_VERBOSE
synctex_node_log(child);
# endif
}
@@ -5260,7 +5260,7 @@ content_loop:
_synctex_node_set_child(parent,ns.node);
}
child = ns.node;
-# if SYNCTEX_VERBOSE
+# ifdef SYNCTEX_VERBOSE
synctex_node_log(child);
# endif
input.node = _synctex_input_register_line(input.node,child);
@@ -5282,7 +5282,7 @@ content_loop:
}
child = ns.node;
_synctex_make_hbox_contain_box(parent,_synctex_data_box(child));
-# if SYNCTEX_VERBOSE
+# ifdef SYNCTEX_VERBOSE
synctex_node_log(child);
# endif
input.node = _synctex_input_register_line(input.node,child);
@@ -5305,7 +5305,7 @@ content_loop:
__synctex_node_make_friend_tlc(child);
}
_synctex_make_hbox_contain_box(parent,_synctex_data_xob(child));
-# if SYNCTEX_VERBOSE
+# ifdef SYNCTEX_VERBOSE
synctex_node_log(child);
# endif
input.node = _synctex_input_register_line(input.node,child);
@@ -5327,7 +5327,7 @@ content_loop:
__synctex_node_make_friend_tlc(child);
}
_synctex_make_hbox_contain_point(parent,_synctex_data_point(child));
-# if SYNCTEX_VERBOSE
+# ifdef SYNCTEX_VERBOSE
synctex_node_log(child);
# endif
input.node = _synctex_input_register_line(input.node,child);
@@ -5351,7 +5351,7 @@ content_loop:
/* Rules are sometimes far too big
_synctex_make_hbox_contain_box(parent,_synctex_data_box(child));
*/
-# if SYNCTEX_VERBOSE
+# ifdef SYNCTEX_VERBOSE
synctex_node_log(child);
# endif
input.node = _synctex_input_register_line(input.node,child);
@@ -5373,7 +5373,7 @@ _synctex_make_hbox_contain_box(parent,_s
__synctex_node_make_friend_tlc(child);
}
_synctex_make_hbox_contain_point(parent,_synctex_data_point(child));
-# if SYNCTEX_VERBOSE
+# ifdef SYNCTEX_VERBOSE
synctex_node_log(child);
# endif
input.node = _synctex_input_register_line(input.node,child);
@@ -5383,7 +5383,7 @@ _synctex_make_hbox_contain_box(parent,_s
# ifdef SYNCTEX_NOTHING
# pragma mark + SCAN FORM REF
# endif
-#if SYNCTEX_DEBUG>500
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>500
synctex_node_display(parent);
synctex_node_display(child);
#endif
@@ -5406,7 +5406,7 @@ _synctex_make_hbox_contain_box(parent,_s
}
scanner->ref_in_sheet = child;
}
-# if SYNCTEX_VERBOSE
+# ifdef SYNCTEX_VERBOSE
synctex_node_log(child);
# endif
goto content_loop;
@@ -5427,7 +5427,7 @@ _synctex_make_hbox_contain_box(parent,_s
__synctex_node_make_friend_tlc(child);
}
_synctex_make_hbox_contain_point(parent,_synctex_data_point(child));
-# if SYNCTEX_VERBOSE
+# ifdef SYNCTEX_VERBOSE
synctex_node_log(child);
# endif
input.node = _synctex_input_register_line(input.node,child);
@@ -5536,7 +5536,7 @@ SYNCTEX_INLINE static synctex_ns_s __syn
sibling->line_index = arg_sibling->line_index;
}
#endif
-#if SYNCTEX_DEBUG>500
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>500
printf("! Ref replacement:\n");
synctex_node_log(ref);
synctex_node_display(synctex_node_sibling(ref));
@@ -5600,7 +5600,7 @@ SYNCTEX_INLINE static synctex_status_t _
}
}
do {
-#if SYNCTEX_DEBUG>500
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>500
printf("POST PROCESSING %s\n",_synctex_node_abstract(proxy));
{
int i,j = 0;
@@ -5619,7 +5619,7 @@ SYNCTEX_INLINE static synctex_status_t _
}
#endif
f(proxy);
-#if SYNCTEX_DEBUG>500
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>500
{
int i,j = 0;
for (i=0;i<proxy->class->scanner->number_of_lists;++i) {
@@ -5638,7 +5638,7 @@ SYNCTEX_INLINE static synctex_status_t _
#endif
/* Side effect: create the hierarchy on the fly */
proxy = synctex_node_next(proxy); /* Change is here */
-#if SYNCTEX_DEBUG>500
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>500
if (proxy) {
int i,j = 0;
for (i=0;i<proxy->class->scanner->number_of_lists;++i) {
@@ -5670,7 +5670,7 @@ SYNCTEX_INLINE static synctex_status_t _
SYNCTEX_INLINE static synctex_status_t _synctex_post_process(synctex_scanner_p scanner) {
synctex_status_t status = SYNCTEX_STATUS_OK;
synctex_ns_s ns = {NULL,SYNCTEX_STATUS_NOT_OK};
-#if SYNCTEX_DEBUG>500
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>500
printf("! entering _synctex_post_process.\n");
synctex_node_display(scanner->sheet);
synctex_node_display(scanner->form);
@@ -5681,7 +5681,7 @@ SYNCTEX_INLINE static synctex_status_t _
if (ns.status<status) {
status = ns.status;
}
-#if SYNCTEX_DEBUG>500
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>500
printf("! ref replaced in form _synctex_post_process.\n");
synctex_node_display(scanner->form);
#endif
@@ -5703,7 +5703,7 @@ SYNCTEX_INLINE static synctex_status_t _
status = ns.status;
}
scanner->ref_in_sheet = NULL;
-#if SYNCTEX_DEBUG>500
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>500
printf("! ref replaced in sheet _synctex_post_process.\n");
synctex_node_display(scanner->sheet);
#endif
@@ -5725,7 +5725,7 @@ SYNCTEX_INLINE static synctex_status_t _
}
}
#endif
-#if SYNCTEX_DEBUG>10000
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>10000
{
int i;
for (i=0;i<scanner->number_of_lists;++i) {
@@ -5746,7 +5746,7 @@ SYNCTEX_INLINE static synctex_status_t _
if (ns.status<status) {
status = ns.status;
}
-#if SYNCTEX_DEBUG>500
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>500
printf("! exiting _synctex_post_process.\n");
synctex_node_display(scanner->sheet);
synctex_node_display(scanner->form);
@@ -5861,7 +5861,7 @@ int synctex_scanner_free(synctex_scanner
synctex_iterator_free(scanner->iterator);
free(scanner->output_fmt);
free(scanner->lists_of_friends);
-#if SYNCTEX_USE_NODE_COUNT>0
+#if defined SYNCTEX_USE_NODE_COUNT && SYNCTEX_USE_NODE_COUNT>0
node_count = scanner->node_count;
#endif
free(scanner);
@@ -5919,7 +5919,7 @@ synctex_scanner_p synctex_scanner_parse(
if (status<SYNCTEX_STATUS_OK) {
_synctex_error("Bad postamble. Ignored\n");
}
-#if SYNCTEX_DEBUG>500
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>500
synctex_scanner_set_display_switcher(scanner, 100);
synctex_node_display(scanner->sheet);
synctex_node_display(scanner->form);
@@ -8048,7 +8048,7 @@ static synctex_nd_s __synctex_closest_de
SYNCTEX_LINEINDEX(node));
#endif
do {
-#if SYNCTEX_DEBUG>500
+#if defined SYNCTEX_DEBUG && SYNCTEX_DEBUG>500
synctex_node_display(child);
#endif
synctex_nd_s nd = SYNCTEX_ND_0;
Index: synctex/synctex_parser_utils.c
===================================================================
--- synctex.orig/synctex_parser_utils.c
+++ synctex/synctex_parser_utils.c
@@ -126,7 +126,7 @@ int _synctex_log(int level, const char *
OutputDebugStringA("\n");
free(buff);
}
-# elif SYNCTEX_USE_SYSLOG
+# elif defined SYNCTEX_USE_SYSLOG
char * buffer1 = NULL;
char * buffer2 = NULL;
openlog ("SyncTeX", LOG_CONS | LOG_PID | LOG_PERROR | LOG_NDELAY, LOG_LOCAL0);

View file

@ -0,0 +1,62 @@
Fix even more compiler warnings
Author: Henrik Fehlauer <rkflx@lab12.net>
Index: synctex/synctex_parser.c
===================================================================
--- synctex.orig/synctex_parser.c
+++ synctex/synctex_parser.c
@@ -529,8 +529,8 @@ typedef struct synctex_reader_t {
char * current; /* current location in the buffer */
char * start; /* start of the buffer */
char * end; /* end of the buffer */
- int min_size;
- int size;
+ size_t min_size;
+ size_t size;
int lastv;
int line_number;
SYNCTEX_DECLARE_CHAR_OFFSET
@@ -759,7 +759,6 @@ synctex_reader_p synctex_reader_init_wit
(char *)_synctex_malloc(reader->size+1); /* one more character for null termination */
if (NULL == reader->start) {
_synctex_error("! malloc error in synctex_reader_init_with_output_file.");
- bailey:
#ifdef SYNCTEX_DEBUG
return reader;
#else
@@ -5293,7 +5292,7 @@ content_loop:
# pragma mark + SCAN KERN
# endif
ns = _synctex_parse_new_kern(scanner);
- continue_scan:
+ /* continue_scan: */
if (ns.status == SYNCTEX_STATUS_OK) {
if (child) {
_synctex_node_set_sibling(child,ns.node);
@@ -6531,7 +6530,7 @@ SYNCTEX_INLINE static synctex_point_s _s
return old;
}
SYNCTEX_INLINE static synctex_box_s _synctex_data_box(synctex_node_p node) {
- synctex_box_s box = {0,0,0,0};
+ synctex_box_s box = {{0,0},{0,0}};
int n;
n = synctex_node_width(node);
if (n<0) {
@@ -6547,7 +6546,7 @@ SYNCTEX_INLINE static synctex_box_s _syn
return box;
}
SYNCTEX_INLINE static synctex_box_s _synctex_data_xob(synctex_node_p node) {
- synctex_box_s box = {0,0,0,0};
+ synctex_box_s box = {{0,0},{0,0}};
int n;
n = synctex_node_width(node);
if (n>0) {
@@ -6563,7 +6562,7 @@ SYNCTEX_INLINE static synctex_box_s _syn
return box;
}
SYNCTEX_INLINE static synctex_box_s _synctex_data_box_V(synctex_node_p node) {
- synctex_box_s box = {0,0,0,0};
+ synctex_box_s box = {{0,0},{0,0}};
int n;
n = _synctex_node_width_V(node);
if (n<0) {

View file

@ -0,0 +1,54 @@
Plug multiple leaks and prevent a segfault:
- When the returned value to be assigned to reader is NULL, reader should be freed beforehand.
- Do not leak memory when scanner creation succeeded, but no synctex file was found.
- A valid reader is the prerequisite for accessing SYNCTEX_FILE.
- Two calls to malloc() for reader->start also require two calls to free().
Author: Henrik Fehlauer <rkflx@lab12.net>
Index: synctex/synctex_parser.c
===================================================================
--- synctex.orig/synctex_parser.c
+++ synctex/synctex_parser.c
@@ -739,6 +739,7 @@ synctex_reader_p synctex_reader_init_wit
if (open.status<SYNCTEX_STATUS_OK) {
open = _synctex_open_v2(output,build_directory,0,synctex_DONT_ADD_QUOTES);
if (open.status<SYNCTEX_STATUS_OK) {
+ synctex_reader_free(reader);
return NULL;
}
}
@@ -5840,6 +5841,7 @@ synctex_scanner_p synctex_scanner_new_wi
#if defined(SYNCTEX_DEBUG)
_synctex_error("No file?");
#endif
+ synctex_scanner_free(scanner);
return NULL;
}
@@ -5848,7 +5850,7 @@ synctex_scanner_p synctex_scanner_new_wi
int synctex_scanner_free(synctex_scanner_p scanner) {
int node_count = 0;
if (scanner) {
- if (SYNCTEX_FILE) {
+ if (scanner->reader && SYNCTEX_FILE) {
gzclose(SYNCTEX_FILE);
SYNCTEX_FILE = NULL;
}
@@ -5883,6 +5885,15 @@ synctex_scanner_p synctex_scanner_parse(
scanner->x_offset = scanner->y_offset = 6.027e23f;
scanner->reader->line_number = 1;
+ /* TODO: cleanup
+ * In some (all?) cases SYNCTEX_START is already initialized
+ * in synctex_reader_init_with_output_file(). Much of the
+ * following code seems like a duplicate and is perhaps a
+ * candidate for deletion. To be on the safe side though, we
+ * keep it for now and just free() any prior malloc() if
+ * existing. */
+ _synctex_free(SYNCTEX_START);
+
SYNCTEX_START = (char *)malloc(SYNCTEX_BUFFER_SIZE+1); /* one more character for null termination */
if (NULL == SYNCTEX_START) {
_synctex_error("! malloc error in synctex_scanner_parse.");

View file

@ -1,8 +1,10 @@
00-disable-SYNCTEX_INLINE.diff
01-fix-win32-define.diff
04-gcc-specify-printf-format.diff
05-fix-error-formats.diff
06-mingw-_synctex_error.diff
07-synctex_scanner_new_with_output_file-reset-mode.diff
08-fix_cpp_comments.diff
09-fix_path_comparison.diff
10-fix-typo.diff
11-fix-unused-parameters-warnings.diff
12-omit-no-file-warning.diff
13-fix-Wundef-warnings.diff
14-fix-misc-compiler-warnings.diff
15-prevent-leaks-and-segfault.diff

File diff suppressed because it is too large Load diff

View file

@ -1,55 +1,50 @@
/*
Copyright (c) 2008, 2009, 2010 , 2011 jerome DOT laurens AT u-bourgogne DOT fr
This file is part of the SyncTeX package.
Latest Revision: Tue Jun 14 08:23:30 UTC 2011
Version: 1.16
See synctex_parser_readme.txt for more details
License:
--------
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE
Except as contained in this notice, the name of the copyright holder
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization from the copyright holder.
Acknowledgments:
----------------
The author received useful remarks from the pdfTeX developers, especially Hahn The Thanh,
and significant help from XeTeX developer Jonathan Kew
Nota Bene:
----------
If you include or use a significant part of the synctex package into a software,
I would appreciate to be listed as contributor and see "SyncTeX" highlighted.
Version 1
Thu Jun 19 09:39:21 UTC 2008
/*
Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr
This file is part of the __SyncTeX__ package.
[//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017)
[//]: # (Version: 1.19)
See `synctex_parser_readme.md` for more details
## License
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE
Except as contained in this notice, the name of the copyright holder
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization from the copyright holder.
## Acknowledgments:
The author received useful remarks from the __pdfTeX__ developers, especially Hahn The Thanh,
and significant help from __XeTeX__ developer Jonathan Kew.
## Nota Bene:
If you include or use a significant part of the __SyncTeX__ package into a software,
I would appreciate to be listed as contributor and see "__SyncTeX__" highlighted.
*/
#ifndef __SYNCTEX_PARSER__
@ -58,286 +53,369 @@ Thu Jun 19 09:39:21 UTC 2008
#ifdef __cplusplus
extern "C" {
#endif
# define SYNCTEX_VERSION_STRING "1.19"
/* The main synctex object is a scanner.
* Its implementation is considered private.
* The basic workflow is
* - create a "synctex scanner" with the contents of a file
* - perform actions on that scanner like
synctex_display_query or synctex_edit_query below.
* - perform actions on nodes returned by the scanner
* - free the scanner when the work is done
*/
typedef struct synctex_scanner_t synctex_scanner_s;
typedef synctex_scanner_s * synctex_scanner_p;
/**
* This is the designated method to create
* a new synctex scanner object.
* - argument output: the pdf/dvi/xdv file associated
* to the synctex file.
* If necessary, it can be the tex file that
* originated the synctex file but this might cause
* problems if the \jobname has a custom value.
* Despite this method can accept a relative path
* in practice, you should only pass full paths.
* The path should be encoded by the underlying
* file system, assuming that it is based on
* 8 bits characters, including UTF8,
* not 16 bits nor 32 bits.
* The last file extension is removed and
* replaced by the proper extension,
* either synctex or synctex.gz.
* - argument build_directory: It is the directory where
* all the auxiliary stuff is created.
* If no synctex file is found in the same directory
* as the output file, then we try to find one in
* this build directory.
* It is the directory where all the auxiliary
* stuff is created. Sometimes, the synctex output
* file and the pdf, dvi or xdv files are not
* created in the same location. See MikTeX.
* This directory path can be NULL,
* it will be ignored then.
* It can be either absolute or relative to the
* directory of the output pdf (dvi or xdv) file.
* Please note that this new argument is provided
* as a convenience but should not be used.
* Available since version 1.5.
* - argument parse: In general, use 1.
* Use 0 only if you do not want to parse the
* content but just check for existence.
* Available since version 1.5
* - resturn: a scanner. NULL is returned in case
* of an error or non existent file.
*/
synctex_scanner_p synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse);
/**
* Designated method to delete a synctex scanner object,
* including all its internal resources.
* Frees all the memory, you must call it when you are finished with the scanner.
* - argument scanner: a scanner.
* - returns: an integer used for testing purposes.
*/
int synctex_scanner_free(synctex_scanner_p scanner);
/**
* Send this message to force the scanner to
* parse the contents of the synctex output file.
* Nothing is performed if the file was already parsed.
* In each query below, this message is sent,
* but if you need to access information more directly,
* you must ensure that the parsing did occur.
* Usage:
* if((my_scanner = synctex_scanner_parse(my_scanner))) {
* continue with my_scanner...
* } else {
* there was a problem
* }
* - returns: the argument on success.
* On failure, frees scanner and returns NULL.
*/
synctex_scanner_p synctex_scanner_parse(synctex_scanner_p scanner);
/* synctex_node_p is the type for all synctex nodes.
* Its implementation is considered private.
* The synctex file is parsed into a tree of nodes, either sheet, form, boxes, math nodes... */
typedef struct synctex_node_t synctex_node_s;
typedef synctex_node_s * synctex_node_p;
/* The main entry points.
* Given the file name, a line and a column number, synctex_display_query returns the number of nodes
* satisfying the contrain. Use code like
*
* if(synctex_display_query(scanner,name,line,column,page_hint)>0) {
* synctex_node_p node;
* while((node = synctex_scanner_next_result(scanner))) {
* // do something with node
* ...
* }
* }
*
* Please notice that since version 1.19,
* there is a new argument page_hint.
* The results in pages closer to page_hint are given first.
* For example, one can
* - highlight each resulting node in the output, using synctex_node_visible_h and synctex_node_visible_v
* - highlight all the rectangles enclosing those nodes, using synctex_node_box_visible_... functions
* - highlight just the character using that information
*
* Given the page and the position in the page, synctex_edit_query returns the number of nodes
* satisfying the contrain. Use code like
*
* if(synctex_edit_query(scanner,page,h,v)>0) {
* synctex_node_p node;
* while(node = synctex_scanner_next_result(scanner)) {
* // do something with node
* ...
* }
* }
*
* For example, one can
* - highlight each resulting line in the input,
* - highlight just the character using that information
*
* page is 1 based
* h and v are coordinates in 72 dpi unit, relative to the top left corner of the page.
* If you make a new query, the result of the previous one is discarded. If you need to make more than one query
* in parallel, use the iterator API exposed in
* the synctex_parser_private.h header.
* If one of this function returns a negative integer,
* it means that an error occurred.
*
* Both methods are conservative, in the sense that matching is weak.
* If the exact column number is not found, there will be an answer with the whole line.
*
* Sumatra-PDF, Skim, iTeXMac2, TeXShop and Texworks are examples of open source software that use this library.
* You can browse their code for a concrete implementation.
*/
typedef long synctex_status_t;
/* The page_hint argument is used to resolve ambiguities.
* Whenever, different matches occur, the ones closest
* to the page will be given first. Pass a negative number
* when in doubt. Using pdf forms may lead to ambiguities.
*/
synctex_status_t synctex_display_query(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint);
synctex_status_t synctex_edit_query(synctex_scanner_p scanner,int page,float h,float v);
synctex_node_p synctex_scanner_next_result(synctex_scanner_p scanner);
synctex_status_t synctex_scanner_reset_result(synctex_scanner_p scanner);
/**
* The horizontal and vertical location,
* the width, height and depth of a box enclosing node.
* All dimensions are given in page coordinates
* as opposite to TeX coordinates.
* The origin is at the top left corner of the page.
* Code example for Qt5:
* (from TeXworks source TWSynchronize.cpp)
* QRectF nodeRect(synctex_node_box_visible_h(node),
* synctex_node_box_visible_v(node) -
* synctex_node_box_visible_height(node),
* synctex_node_box_visible_width(node),
* synctex_node_box_visible_height(node) +
* synctex_node_box_visible_depth(node));
* Code example for Cocoa:
* NSRect bounds = [pdfPage
* boundsForBox:kPDFDisplayBoxMediaBox];
* NSRect nodeRect = NSMakeRect(
* synctex_node_box_visible_h(node),
* NSMaxY(bounds)-synctex_node_box_visible_v(node) +
* synctex_node_box_visible_height(node),
* synctex_node_box_visible_width(node),
* synctex_node_box_visible_height(node) +
* synctex_node_box_visible_depth(node)
* );
* The visible dimensions are bigger than real ones
* to compensate 0 width boxes or nodes intentionnaly
* put outside the box (using \kern for example).
* - parameter node: a node.
* - returns: a float.
* - author: JL
*/
float synctex_node_box_visible_h(synctex_node_p node);
float synctex_node_box_visible_v(synctex_node_p node);
float synctex_node_box_visible_width(synctex_node_p node);
float synctex_node_box_visible_height(synctex_node_p node);
float synctex_node_box_visible_depth(synctex_node_p node);
/* synctex_node_t is the type for all synctex nodes.
* The synctex file is parsed into a tree of nodes, either sheet, boxes, math nodes... */
typedef struct _synctex_node * synctex_node_t;
/**
* For quite all nodes, horizontal and vertical coordinates, and width.
* All dimensions are given in page coordinates
* as opposite to TeX coordinates.
* The origin is at the top left corner of the page.
* The visible dimensions are bigger than real ones
* to compensate 0 width boxes or nodes intentionnaly
* put outside the box (using \kern for example).
* All nodes have coordinates, but all nodes don't
* have non null size. For example, math nodes
* have no width according to TeX, and in that case
* synctex_node_visible_width simply returns 0.
* The same holds for kern nodes that do not have
* height nor depth, etc...
*/
float synctex_node_visible_h(synctex_node_p node);
float synctex_node_visible_v(synctex_node_p node);
float synctex_node_visible_width(synctex_node_p node);
float synctex_node_visible_height(synctex_node_p node);
float synctex_node_visible_depth(synctex_node_p node);
/* The main synctex object is a scanner
* Its implementation is considered private.
* The basic workflow is
* - create a "synctex scanner" with the contents of a file
* - perform actions on that scanner like display or edit queries
* - free the scanner when the work is done
*/
typedef struct __synctex_scanner_t _synctex_scanner_t;
typedef _synctex_scanner_t * synctex_scanner_t;
/**
* Given a node, access to its tag, line and column.
* The line and column numbers are 1 based.
* The latter is not yet fully supported in TeX,
* the default implementation returns 0
* which means the whole line.
* synctex_node_get_name returns the path of the
* TeX source file that was used to create the node.
* When the tag is known, the scanner of the node
* will also give that same file name, see
* synctex_scanner_get_name below.
*/
int synctex_node_tag(synctex_node_p node);
int synctex_node_line(synctex_node_p node);
int synctex_node_column(synctex_node_p node);
const char * synctex_node_get_name(synctex_node_p node);
/* This is the designated method to create a new synctex scanner object.
* output is the pdf/dvi/xdv file associated to the synctex file.
* If necessary, it can be the tex file that originated the synctex file
* but this might cause problems if the \jobname has a custom value.
* Despite this method can accept a relative path in practice,
* you should only pass a full path name.
* The path should be encoded by the underlying file system,
* assuming that it is based on 8 bits characters, including UTF8,
* not 16 bits nor 32 bits.
* The last file extension is removed and replaced by the proper extension.
* Then the private method _synctex_scanner_new_with_contents_of_file is called.
* NULL is returned in case of an error or non existent file.
* Once you have a scanner, use the synctex_display_query and synctex_edit_query below.
* The new "build_directory" argument is available since version 1.5.
* It is the directory where all the auxiliary stuff is created.
* Sometimes, the synctex output file and the pdf, dvi or xdv files are not created in the same directory.
* This is the case in MikTeX (I will include this into TeX Live).
* This directory path can be nil, it will be ignored then.
* It can be either absolute or relative to the directory of the output pdf (dvi or xdv) file.
* If no synctex file is found in the same directory as the output file, then we try to find one in the build directory.
* Please note that this new "build_directory" is provided as a convenient argument but should not be used.
* In fact, this is implempented as a work around of a bug in MikTeX where the synctex file does not follow the pdf file.
* The new "parse" argument is available since version 1.5. In general, use 1.
* Use 0 only if you do not want to parse the content but just check the existence.
*/
synctex_scanner_t synctex_scanner_new_with_output_file(const char * output, const char * build_directory, int parse);
/**
This is the page where the node appears.
* This is a 1 based index as given by TeX.
*/
int synctex_node_page(synctex_node_p node);
/* This is the designated method to delete a synctex scanner object.
* Frees all the memory, you must call it when you are finished with the scanner.
*/
void synctex_scanner_free(synctex_scanner_t scanner);
/* Send this message to force the scanner to parse the contents of the synctex output file.
* Nothing is performed if the file was already parsed.
* In each query below, this message is sent, but if you need to access information more directly,
* you must be sure that the parsing did occur.
* Usage:
* if((my_scanner = synctex_scanner_parse(my_scanner))) {
* continue with my_scanner...
* } else {
* there was a problem
* }
*/
synctex_scanner_t synctex_scanner_parse(synctex_scanner_t scanner);
/* The main entry points.
* Given the file name, a line and a column number, synctex_display_query returns the number of nodes
* satisfying the contrain. Use code like
*
* if(synctex_display_query(scanner,name,line,column)>0) {
* synctex_node_t node;
* while((node = synctex_next_result(scanner))) {
* // do something with node
* ...
* }
* }
*
* For example, one can
* - highlight each resulting node in the output, using synctex_node_h and synctex_node_v
* - highlight all the rectangles enclosing those nodes, using synctex_box_... functions
* - highlight just the character using that information
*
* Given the page and the position in the page, synctex_edit_query returns the number of nodes
* satisfying the contrain. Use code like
*
* if(synctex_edit_query(scanner,page,h,v)>0) {
* synctex_node_t node;
* while(node = synctex_next_result(scanner)) {
* // do something with node
* ...
* }
* }
*
* For example, one can
* - highlight each resulting line in the input,
* - highlight just the character using that information
*
* page is 1 based
* h and v are coordinates in 72 dpi unit, relative to the top left corner of the page.
* If you make a new query, the result of the previous one is discarded.
* If one of this function returns a non positive integer,
* it means that an error occurred.
*
* Both methods are conservative, in the sense that matching is weak.
* If the exact column number is not found, there will be an answer with the whole line.
*
* Sumatra-PDF, Skim, iTeXMac2 and Texworks are examples of open source software that use this library.
* You can browse their code for a concrete implementation.
*/
int synctex_display_query(synctex_scanner_t scanner,const char * name,int line,int column);
int synctex_edit_query(synctex_scanner_t scanner,int page,float h,float v);
synctex_node_t synctex_next_result(synctex_scanner_t scanner);
/* Display all the information contained in the scanner object.
* If the records are too numerous, only the first ones are displayed.
* This is mainly for informatinal purpose to help developers.
*/
void synctex_scanner_display(synctex_scanner_t scanner);
/* The x and y offset of the origin in TeX coordinates. The magnification
These are used by pdf viewers that want to display the real box size.
For example, getting the horizontal coordinates of a node would require
synctex_node_box_h(node)*synctex_scanner_magnification(scanner)+synctex_scanner_x_offset(scanner)
Getting its TeX width would simply require
synctex_node_box_width(node)*synctex_scanner_magnification(scanner)
but direct methods are available for that below.
*/
int synctex_scanner_x_offset(synctex_scanner_t scanner);
int synctex_scanner_y_offset(synctex_scanner_t scanner);
float synctex_scanner_magnification(synctex_scanner_t scanner);
/* Managing the input file names.
* Given a tag, synctex_scanner_get_name will return the corresponding file name.
* Conversely, given a file name, synctex_scanner_get_tag will retur, the corresponding tag.
* The file name must be the very same as understood by TeX.
* For example, if you \input myDir/foo.tex, the file name is myDir/foo.tex.
* No automatic path expansion is performed.
* Finally, synctex_scanner_input is the first input node of the scanner.
* To browse all the input node, use a loop like
*
* if((input_node = synctex_scanner_input(scanner))){
* do {
* blah
* } while((input_node=synctex_node_sibling(input_node)));
* }
*
* The output is the name that was used to create the scanner.
* The synctex is the real name of the synctex file,
* it was obtained from output by setting the proper file extension.
*/
const char * synctex_scanner_get_name(synctex_scanner_t scanner,int tag);
int synctex_scanner_get_tag(synctex_scanner_t scanner,const char * name);
synctex_node_t synctex_scanner_input(synctex_scanner_t scanner);
const char * synctex_scanner_get_output(synctex_scanner_t scanner);
const char * synctex_scanner_get_synctex(synctex_scanner_t scanner);
/* Browsing the nodes
* parent, child and sibling are standard names for tree nodes.
* The parent is one level higher, the child is one level deeper,
* and the sibling is at the same level.
* The sheet of a node is the first ancestor, it is of type sheet.
* A node and its sibling have the same parent.
* A node is the parent of its child.
* A node is either the child of its parent,
* or belongs to the sibling chain of its parent's child.
* The next node is either the child, the sibling or the parent's sibling,
* unless the parent is a sheet.
* This allows to navigate through all the nodes of a given sheet node:
*
* synctex_node_t node = sheet;
* while((node = synctex_node_next(node))) {
* // do something with node
* }
*
* With synctex_sheet_content, you can retrieve the sheet node given the page.
* The page is 1 based, according to TeX standards.
* Conversely synctex_node_sheet allows to retrieve the sheet containing a given node.
*/
synctex_node_t synctex_node_parent(synctex_node_t node);
synctex_node_t synctex_node_sheet(synctex_node_t node);
synctex_node_t synctex_node_child(synctex_node_t node);
synctex_node_t synctex_node_sibling(synctex_node_t node);
synctex_node_t synctex_node_next(synctex_node_t node);
synctex_node_t synctex_sheet_content(synctex_scanner_t scanner,int page);
/* These are the types of the synctex nodes */
typedef enum {
synctex_node_type_error = 0,
synctex_node_type_input,
synctex_node_type_sheet,
synctex_node_type_vbox,
synctex_node_type_void_vbox,
synctex_node_type_hbox,
synctex_node_type_void_hbox,
synctex_node_type_kern,
synctex_node_type_glue,
synctex_node_type_math,
synctex_node_type_boundary,
synctex_node_number_of_types
} synctex_node_type_t;
/* synctex_node_type gives the type of a given node,
* synctex_node_isa gives the same information as a human readable text. */
synctex_node_type_t synctex_node_type(synctex_node_t node);
const char * synctex_node_isa(synctex_node_t node);
/* This is primarily used for debugging purpose.
* The second one logs information for the node and recursively displays information for its next node */
void synctex_node_log(synctex_node_t node);
void synctex_node_display(synctex_node_t node);
/* Given a node, access to its tag, line and column.
* The line and column numbers are 1 based.
* The latter is not yet fully supported in TeX, the default implementation returns 0 which means the whole line.
* When the tag is known, the scanner of the node will give the corresponding file name.
* When the tag is known, the scanner of the node will give the name.
*/
int synctex_node_tag(synctex_node_t node);
int synctex_node_line(synctex_node_t node);
int synctex_node_column(synctex_node_t node);
/* This is the page where the node appears.
* This is a 1 based index as given by TeX.
*/
int synctex_node_page(synctex_node_t node);
/* For quite all nodes, horizontal, vertical coordinates, and width.
* These are expressed in TeX small points coordinates, with origin at the top left corner.
*/
int synctex_node_h(synctex_node_t node);
int synctex_node_v(synctex_node_t node);
int synctex_node_width(synctex_node_t node);
/* For all nodes, dimensions of the enclosing box.
* These are expressed in TeX small points coordinates, with origin at the top left corner.
* A box is enclosing itself.
*/
int synctex_node_box_h(synctex_node_t node);
int synctex_node_box_v(synctex_node_t node);
int synctex_node_box_width(synctex_node_t node);
int synctex_node_box_height(synctex_node_t node);
int synctex_node_box_depth(synctex_node_t node);
/* For quite all nodes, horizontal, vertical coordinates, and width.
* The visible dimensions are bigger than real ones to compensate 0 width boxes
* that do contain nodes.
* These are expressed in page coordinates, with origin at the top left corner.
* A box is enclosing itself.
*/
float synctex_node_visible_h(synctex_node_t node);
float synctex_node_visible_v(synctex_node_t node);
float synctex_node_visible_width(synctex_node_t node);
/* For all nodes, visible dimensions of the enclosing box.
* A box is enclosing itself.
* The visible dimensions are bigger than real ones to compensate 0 width boxes
* that do contain nodes.
*/
float synctex_node_box_visible_h(synctex_node_t node);
float synctex_node_box_visible_v(synctex_node_t node);
float synctex_node_box_visible_width(synctex_node_t node);
float synctex_node_box_visible_height(synctex_node_t node);
float synctex_node_box_visible_depth(synctex_node_t node);
/* The main synctex updater object.
* This object is used to append information to the synctex file.
* Its implementation is considered private.
* It is used by the synctex command line tool to take into account modifications
* that could occur while postprocessing files by dvipdf like filters.
*/
typedef struct __synctex_updater_t _synctex_updater_t;
typedef _synctex_updater_t * synctex_updater_t;
/* Designated initializer.
* Once you are done with your whole job,
* free the updater */
synctex_updater_t synctex_updater_new_with_output_file(const char * output, const char * directory);
/* Use the next functions to append records to the synctex file,
* no consistency tests made on the arguments */
void synctex_updater_append_magnification(synctex_updater_t updater, char * magnification);
void synctex_updater_append_x_offset(synctex_updater_t updater, char * x_offset);
void synctex_updater_append_y_offset(synctex_updater_t updater, char * y_offset);
/* You MUST free the updater, once everything is properly appended */
void synctex_updater_free(synctex_updater_t updater);
/**
* Display all the information contained in the scanner.
* If the records are too numerous, only the first ones are displayed.
* This is mainly for informational purpose to help developers.
*/
void synctex_scanner_display(synctex_scanner_p scanner);
/* Managing the input file names.
* Given a tag, synctex_scanner_get_name will return the corresponding file name.
* Conversely, given a file name, synctex_scanner_get_tag will return, the corresponding tag.
* The file name must be the very same as understood by TeX.
* For example, if you \input myDir/foo.tex, the file name is myDir/foo.tex.
* No automatic path expansion is performed.
* Finally, synctex_scanner_input is the first input node of the scanner.
* To browse all the input node, use a loop like
* ...
* synctex_node_p = input_node;
* ...
* if((input_node = synctex_scanner_input(scanner))) {
* do {
* blah
* } while((input_node=synctex_node_sibling(input_node)));
* }
*
* The output is the name that was used to create the scanner.
* The synctex is the real name of the synctex file,
* it was obtained from output by setting the proper file extension.
*/
const char * synctex_scanner_get_name(synctex_scanner_p scanner,int tag);
int synctex_scanner_get_tag(synctex_scanner_p scanner,const char * name);
synctex_node_p synctex_scanner_input(synctex_scanner_p scanner);
synctex_node_p synctex_scanner_input_with_tag(synctex_scanner_p scanner,int tag);
const char * synctex_scanner_get_output(synctex_scanner_p scanner);
const char * synctex_scanner_get_synctex(synctex_scanner_p scanner);
/* The x and y offset of the origin in TeX coordinates. The magnification
These are used by pdf viewers that want to display the real box size.
For example, getting the horizontal coordinates of a node would require
synctex_node_box_h(node)*synctex_scanner_magnification(scanner)+synctex_scanner_x_offset(scanner)
Getting its TeX width would simply require
synctex_node_box_width(node)*synctex_scanner_magnification(scanner)
but direct methods are available for that below.
*/
int synctex_scanner_x_offset(synctex_scanner_p scanner);
int synctex_scanner_y_offset(synctex_scanner_p scanner);
float synctex_scanner_magnification(synctex_scanner_p scanner);
/**
* ## Browsing the nodes
* parent, child and sibling are standard names for tree nodes.
* The parent is one level higher,
* the child is one level deeper,
* and the sibling is at the same level.
* A node and its sibling have the same parent.
* A node is the parent of its children.
* A node is either the child of its parent,
* or belongs to the sibling chain of its parent's child.
* The sheet or form of a node is the topmost ancestor,
* it is of type sheet or form.
* The next node is either the child, the sibling or the parent's sibling,
* unless the parent is a sheet, a form or NULL.
* This allows to navigate through all the nodes of a given sheet node:
*
* synctex_node_p node = sheet;
* while((node = synctex_node_next(node))) {
* // do something with node
* }
*
* With synctex_sheet_content and synctex_form_content,
* you can retrieve the sheet node given the page
* or form tag.
* The page is 1 based, according to TeX standards.
* Conversely synctex_node_parent_sheet or
* synctex_node_parent_form allows to retrieve
* the sheet or the form containing a given node.
* Notice that a node is not contained in a sheet
* and a form at the same time.
* Some nodes are not contained in either (handles).
*/
synctex_node_p synctex_node_parent(synctex_node_p node);
synctex_node_p synctex_node_parent_sheet(synctex_node_p node);
synctex_node_p synctex_node_parent_form(synctex_node_p node);
synctex_node_p synctex_node_child(synctex_node_p node);
synctex_node_p synctex_node_last_child(synctex_node_p node);
synctex_node_p synctex_node_sibling(synctex_node_p node);
synctex_node_p synctex_node_last_sibling(synctex_node_p node);
synctex_node_p synctex_node_arg_sibling(synctex_node_p node);
synctex_node_p synctex_node_next(synctex_node_p node);
/**
* Top level entry points.
* The scanner owns a list of sheet siblings and
* a list of form siblings.
* Sheets or forms have one child which is a box:
* theie contents.
* - argument page: 1 based sheet page number.
* - argument tag: 1 based form tag number.
*/
synctex_node_p synctex_sheet(synctex_scanner_p scanner,int page);
synctex_node_p synctex_sheet_content(synctex_scanner_p scanner,int page);
synctex_node_p synctex_form(synctex_scanner_p scanner,int tag);
synctex_node_p synctex_form_content(synctex_scanner_p scanner,int tag);
/* This is primarily used for debugging purpose.
* The second one logs information for the node and recursively displays information for its next node */
void synctex_node_log(synctex_node_p node);
void synctex_node_display(synctex_node_p node);
/* For quite all nodes, horizontal, vertical coordinates, and width.
* These are expressed in TeX small points coordinates, with origin at the top left corner.
*/
int synctex_node_h(synctex_node_p node);
int synctex_node_v(synctex_node_p node);
int synctex_node_width(synctex_node_p node);
int synctex_node_height(synctex_node_p node);
int synctex_node_depth(synctex_node_p node);
/* For all nodes, dimensions of the enclosing box.
* These are expressed in TeX small points coordinates, with origin at the top left corner.
* A box is enclosing itself.
*/
int synctex_node_box_h(synctex_node_p node);
int synctex_node_box_v(synctex_node_p node);
int synctex_node_box_width(synctex_node_p node);
int synctex_node_box_height(synctex_node_p node);
int synctex_node_box_depth(synctex_node_p node);
#ifdef __cplusplus
}

View file

@ -0,0 +1,552 @@
/*
Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr
This file is part of the __SyncTeX__ package.
[//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017)
[//]: # (Version: 1.19)
See `synctex_parser_readme.md` for more details
## License
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE
Except as contained in this notice, the name of the copyright holder
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization from the copyright holder.
*/
#include "synctex_parser.h"
#include "synctex_parser_utils.h"
#ifndef __SYNCTEX_PARSER_PRIVATE__
# define __SYNCTEX_PARSER_PRIVATE__
#ifdef __cplusplus
extern "C" {
#endif
/* Reminder that the argument must not be NULL */
typedef synctex_node_p synctex_non_null_node_p;
/* Each node of the tree, except the scanner itself belongs to a class.
* The class object is just a struct declaring the owning scanner
* This is a pointer to the scanner as root of the tree.
* The type is used to identify the kind of node.
* The class declares pointers to a creator and a destructor method.
* The log and display fields are used to log and display the node.
* display will also display the child, sibling and parent sibling.
* parent, child and sibling are used to navigate the tree,
* from TeX box hierarchy point of view.
* The friend field points to a method which allows to navigate from friend to friend.
* A friend is a node with very close tag and line numbers.
* Finally, the info field point to a method giving the private node info offset.
*/
/**
* These are the masks for the synctex node types.
* int's are 32 bits at leats.
*/
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
};
enum {
synctex_mask_root = 1,
synctex_mask_no_root = synctex_mask_root<<1,
synctex_mask_void = synctex_mask_no_root<<1,
synctex_mask_no_void = synctex_mask_void<<1,
synctex_mask_box = synctex_mask_no_void<<1,
synctex_mask_no_box = synctex_mask_box<<1,
synctex_mask_proxy = synctex_mask_no_box<<1,
synctex_mask_no_proxy = synctex_mask_proxy<<1,
synctex_mask_h = synctex_mask_no_proxy<<1,
synctex_mask_v = synctex_mask_h<<1,
};
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
};
typedef enum {
synctex_node_mask_sf =
synctex_mask_root
|synctex_mask_no_void
|synctex_mask_no_box
|synctex_mask_no_proxy,
synctex_node_mask_vbox =
synctex_mask_no_root
|synctex_mask_no_void
|synctex_mask_box
|synctex_mask_no_proxy
|synctex_mask_v,
synctex_node_mask_hbox =
synctex_mask_no_root
|synctex_mask_no_void
|synctex_mask_box
|synctex_mask_no_proxy
|synctex_mask_h,
synctex_node_mask_void_vbox =
synctex_mask_no_root
|synctex_mask_void
|synctex_mask_box
|synctex_mask_no_proxy
|synctex_mask_v,
synctex_node_mask_void_hbox =
synctex_mask_no_root
|synctex_mask_void
|synctex_mask_box
|synctex_mask_no_proxy
|synctex_mask_h,
synctex_node_mask_vbox_proxy =
synctex_mask_no_root
|synctex_mask_no_void
|synctex_mask_box
|synctex_mask_proxy
|synctex_mask_v,
synctex_node_mask_hbox_proxy =
synctex_mask_no_root
|synctex_mask_no_void
|synctex_mask_box
|synctex_mask_proxy
|synctex_mask_h,
synctex_node_mask_nvnn =
synctex_mask_no_root
|synctex_mask_void
|synctex_mask_no_box
|synctex_mask_no_proxy,
synctex_node_mask_input =
synctex_mask_root
|synctex_mask_void
|synctex_mask_no_box
|synctex_mask_no_proxy,
synctex_node_mask_proxy =
synctex_mask_no_root
|synctex_mask_void
|synctex_mask_no_box
|synctex_mask_proxy
} synctex_node_mask_t;
enum {
/* input */
synctex_tree_sibling_idx = 0,
synctex_tree_s_input_max = 1,
/* All */
synctex_tree_s_parent_idx = 1,
synctex_tree_sp_child_idx = 2,
synctex_tree_spc_friend_idx = 3,
synctex_tree_spcf_last_idx = 4,
synctex_tree_spcfl_vbox_max = 5,
/* hbox supplement */
synctex_tree_spcfl_next_hbox_idx = 5,
synctex_tree_spcfln_hbox_max = 6,
/* hbox proxy supplement */
synctex_tree_spcfln_target_idx = 6,
synctex_tree_spcflnt_proxy_hbox_max = 7,
/* vbox proxy supplement */
synctex_tree_spcfl_target_idx = 5,
synctex_tree_spcflt_proxy_vbox_max = 6,
/* spf supplement*/
synctex_tree_sp_friend_idx = 2,
synctex_tree_spf_max = 3,
/* box boundary supplement */
synctex_tree_spf_arg_sibling_idx = 3,
synctex_tree_spfa_max = 4,
/* proxy supplement */
synctex_tree_spf_target_idx = 3,
synctex_tree_spft_proxy_max = 4,
/* last proxy supplement */
synctex_tree_spfa_target_idx = 4,
synctex_tree_spfat_proxy_last_max = 5,
/* sheet supplement */
synctex_tree_s_child_idx = 1,
synctex_tree_sc_next_hbox_idx = 2,
synctex_tree_scn_sheet_max = 3,
/* form supplement */
synctex_tree_sc_target_idx = 2,
synctex_tree_sct_form_max = 3,
/* spct */
synctex_tree_spc_target_idx = 3,
synctex_tree_spct_handle_max = 4,
};
enum {
/* input */
synctex_data_input_tag_idx = 0,
synctex_data_input_line_idx = 1,
synctex_data_input_name_idx = 2,
synctex_data_input_tln_max = 3,
/* sheet */
synctex_data_sheet_page_idx = 0,
synctex_data_p_sheet_max = 1,
/* form */
synctex_data_form_tag_idx = 0,
synctex_data_t_form_max = 1,
/* tlchv */
synctex_data_tag_idx = 0,
synctex_data_line_idx = 1,
synctex_data_column_idx = 2,
synctex_data_h_idx = 3,
synctex_data_v_idx = 4,
synctex_data_tlchv_max = 5,
/* tlchvw */
synctex_data_width_idx = 5,
synctex_data_tlchvw_max = 6,
/* box */
synctex_data_height_idx = 6,
synctex_data_depth_idx = 7,
synctex_data_box_max = 8,
/* hbox supplement */
synctex_data_mean_line_idx = 8,
synctex_data_weight_idx = 9,
synctex_data_h_V_idx = 10,
synctex_data_v_V_idx = 11,
synctex_data_width_V_idx = 12,
synctex_data_height_V_idx = 13,
synctex_data_depth_V_idx = 14,
synctex_data_hbox_max = 15,
/* ref */
synctex_data_ref_tag_idx = 0,
synctex_data_ref_h_idx = 1,
synctex_data_ref_v_idx = 2,
synctex_data_ref_thv_max = 3,
/* proxy */
synctex_data_proxy_h_idx = 0,
synctex_data_proxy_v_idx = 1,
synctex_data_proxy_hv_max = 2,
};
/* each synctex node has a class */
typedef struct synctex_class_t synctex_class_s;
typedef synctex_class_s * synctex_class_p;
/* synctex_node_p is a pointer to a node
* synctex_node_s is the target of the synctex_node_p pointer
* It is a pseudo object oriented program.
* class is a pointer to the class object the node belongs to.
* implementation is meant to contain the private data of the node
* basically, there are 2 kinds of information: navigation information and
* synctex information. Both will depend on the type of the node,
* thus different nodes will have different private data.
* There is no inheritancy overhead.
*/
typedef union {
synctex_node_p as_node;
int as_integer;
char * as_string;
void * as_pointer;
} synctex_data_u;
typedef synctex_data_u * synctex_data_p;
# if defined(SYNCTEX_USE_CHARINDEX)
typedef unsigned int synctex_charindex_t;
synctex_charindex_t synctex_node_charindex(synctex_node_p node);
typedef synctex_charindex_t synctex_lineindex_t;
synctex_lineindex_t synctex_node_lineindex(synctex_node_p node);
synctex_node_p synctex_scanner_handle(synctex_scanner_p scanner);
# define SYNCTEX_DECLARE_CHARINDEX \
synctex_charindex_t char_index;\
synctex_lineindex_t line_index;
# define SYNCTEX_DECLARE_CHAR_OFFSET \
synctex_charindex_t charindex_offset;
# else
# define SYNCTEX_DECLARE_CHARINDEX
# define SYNCTEX_DECLARE_CHAR_OFFSET
# endif
struct synctex_node_t {
SYNCTEX_DECLARE_CHARINDEX
synctex_class_p class;
#ifdef DEBUG
synctex_data_u data[22];
#else
synctex_data_u data[1];
#endif
};
typedef synctex_node_p * synctex_node_r;
typedef struct {
int h;
int v;
} synctex_point_s;
typedef synctex_point_s * synctex_point_p;
typedef struct {
synctex_point_s min; /* top left */
synctex_point_s max; /* bottom right */
} synctex_box_s;
typedef synctex_box_s * synctex_box_p;
/**
* These are the types of the synctex nodes.
* No need to use them but the compiler needs them here.
* There are 3 kinds of nodes.
* - primary nodes
* - proxies
* - handles
* Primary nodes are created at parse time
* of the synctex file.
* Proxies are used to support pdf forms.
* The ref primary nodes are replaced by a tree
* of proxy nodes which duplicate the tree of primary
* nodes available in the refered form.
* Roughly speaking, the primary nodes of the form
* know what to display, the proxy nodes know where.
* Handles are used in queries. They point to either
* primary nodes or proxies.
*/
typedef enum {
synctex_node_type_none = 0,
synctex_node_type_input,
synctex_node_type_sheet,
synctex_node_type_form,
synctex_node_type_ref,
synctex_node_type_vbox,
synctex_node_type_void_vbox,
synctex_node_type_hbox,
synctex_node_type_void_hbox,
synctex_node_type_kern,
synctex_node_type_glue,
synctex_node_type_rule,
synctex_node_type_math,
synctex_node_type_boundary,
synctex_node_type_box_bdry,
synctex_node_type_proxy,
synctex_node_type_proxy_last,
synctex_node_type_proxy_vbox,
synctex_node_type_proxy_hbox,
synctex_node_type_handle,
synctex_node_number_of_types
} synctex_node_type_t;
/* synctex_node_type gives the type of a given node,
* synctex_node_isa gives the same information as a human readable text. */
synctex_node_type_t synctex_node_type(synctex_node_p node);
const char * synctex_node_isa(synctex_node_p node);
synctex_node_type_t synctex_node_target_type(synctex_node_p node);
synctex_node_type_t synctex_node_type(synctex_node_p node);
const char * synctex_node_isa(synctex_node_p node);
void synctex_node_log(synctex_node_p node);
void synctex_node_display(synctex_node_p node);
/* Given a node, access to the location in the synctex file where it is defined.
*/
int synctex_node_form_tag(synctex_node_p node);
int synctex_node_mean_line(synctex_node_p node);
int synctex_node_weight(synctex_node_p node);
int synctex_node_child_count(synctex_node_p node);
int synctex_node_h(synctex_node_p node);
int synctex_node_v(synctex_node_p node);
int synctex_node_width(synctex_node_p node);
int synctex_node_box_h(synctex_node_p node);
int synctex_node_box_v(synctex_node_p node);
int synctex_node_box_width(synctex_node_p node);
int synctex_node_box_height(synctex_node_p node);
int synctex_node_box_depth(synctex_node_p node);
int synctex_node_hbox_h(synctex_node_p node);
int synctex_node_hbox_v(synctex_node_p node);
int synctex_node_hbox_width(synctex_node_p node);
int synctex_node_hbox_height(synctex_node_p node);
int synctex_node_hbox_depth(synctex_node_p node);
synctex_scanner_p synctex_scanner_new();
synctex_node_p synctex_node_new(synctex_scanner_p scanner,synctex_node_type_t type);
/**
* Scanner display switcher getter.
* If the switcher is 0, synctex_node_display is disabled.
* If the switcher is <0, synctex_node_display has no limit.
* If the switcher is >0, only the first switcher (as number) nodes are displayed.
* - parameter: a scanner
* - returns: an integer
*/
int synctex_scanner_display_switcher(synctex_scanner_p scanR);
void synctex_scanner_set_display_switcher(synctex_scanner_p scanR, int switcher);
/**
* Iterator is the structure used to traverse
* the answer to client queries.
* First answers are the best matches, according
* to criteria explained below.
* Next answers are not ordered.
* Objects are handles to nodes in the synctex node tree starting at scanner.
*/
typedef struct synctex_iterator_t synctex_iterator_s;
typedef synctex_iterator_s * synctex_iterator_p;
/**
* Designated creator for a display query, id est,
* forward navigation from source to output.
* Returns NULL if the query has no answer.
* Code example:
* synctex_iterator_p iterator = NULL;
* if ((iterator = synctex_iterator_new_display(...)) {
* synctex_node_p node = NULL;
* while((node = synctex_iterator_next_result(iterator))) {
* do something with node...
* }
*/
synctex_iterator_p synctex_iterator_new_display(synctex_scanner_p scanner,const char * name,int line,int column, int page_hint);
/**
* Designated creator for an edit query, id est,
* backward navigation from output to source.
* Code example:
* synctex_iterator_p iterator = NULL;
* if ((iterator = synctex_iterator_new_edit(...)) {
* synctex_node_p node = NULL;
* while((node = synctex_iterator_next_result(iterator))) {
* do something with node...
* }
*/
synctex_iterator_p synctex_iterator_new_edit(synctex_scanner_p scanner,int page,float h,float v);
/**
* Free all the resources.
* - argument iterator: the object to free...
* You should free the iterator before the scanner
* owning the nodes it iterates with.
*/
void synctex_iterator_free(synctex_iterator_p iterator);
/**
* Wether the iterator actually points to an object.
* - argument iterator: the object to iterate on...
*/
synctex_bool_t synctex_iterator_has_next(synctex_iterator_p iterator);
/**
* Returns the pointed object and advance the cursor
* to the next object. Returns NULL and does nothing
* if the end has already been reached.
* - argument iterator: the object to iterate on...
*/
synctex_node_p synctex_iterator_next_result(synctex_iterator_p iterator);
/**
* Reset the cursor position to the first result.
* - argument iterator: the object to iterate on...
*/
int synctex_iterator_reset(synctex_iterator_p iterator);
/**
* The number of objects left for traversal.
* - argument iterator: the object to iterate on...
*/
int synctex_iterator_count(synctex_iterator_p iterator);
/**
* The target of the node, either a handle or a proxy.
*/
synctex_node_p synctex_node_target(synctex_node_p node);
#ifndef SYNCTEX_NO_UPDATER
/* The main synctex updater object.
* This object is used to append information to the synctex file.
* Its implementation is considered private.
* It is used by the synctex command line tool to take into account modifications
* that could occur while postprocessing files by dvipdf like filters.
*/
typedef struct synctex_updater_t synctex_updater_s;
typedef synctex_updater_s * synctex_updater_p;
/* Designated initializer.
* Once you are done with your whole job,
* free the updater */
synctex_updater_p synctex_updater_new_with_output_file(const char * output, const char * directory);
/* Use the next functions to append records to the synctex file,
* no consistency tests made on the arguments */
void synctex_updater_append_magnification(synctex_updater_p updater, char * magnification);
void synctex_updater_append_x_offset(synctex_updater_p updater, char * x_offset);
void synctex_updater_append_y_offset(synctex_updater_p updater, char * y_offset);
/* You MUST free the updater, once everything is properly appended */
void synctex_updater_free(synctex_updater_p updater);
#endif
#if defined(SYNCTEX_DEBUG)
# include "assert.h"
# define SYNCTEX_ASSERT assert
#else
# define SYNCTEX_ASSERT(UNUSED)
#endif
#if defined(SYNCTEX_TESTING)
#warning TESTING IS PROHIBITED
#if __clang__
#define __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wformat-extra-args\"")
#define __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS _Pragma("clang diagnostic pop")
#else
#define __PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS
#define __PRAGMA_POP_NO_EXTRA_ARG_WARNINGS
#endif
# define SYNCTEX_TEST_BODY(counter, condition, desc, ...) \
do { \
__PRAGMA_PUSH_NO_EXTRA_ARG_WARNINGS \
if (!(condition)) { \
++counter; \
printf("**** Test failed: %s\nfile %s\nfunction %s\nline %i\n",#condition,__FILE__,__FUNCTION__,__LINE__); \
printf((desc), ##__VA_ARGS__); \
} \
__PRAGMA_POP_NO_EXTRA_ARG_WARNINGS \
} while(0)
# define SYNCTEX_TEST_PARAMETER(counter, condition) SYNCTEX_TEST_BODY(counter, (condition), "Invalid parameter not satisfying: %s", #condition)
int synctex_test_input(synctex_scanner_p scanner);
int synctex_test_proxy(synctex_scanner_p scanner);
int synctex_test_tree(synctex_scanner_p scanner);
int synctex_test_page(synctex_scanner_p scanner);
int synctex_test_handle(synctex_scanner_p scanner);
int synctex_test_display_query(synctex_scanner_p scanner);
int synctex_test_charindex();
int synctex_test_sheet_1();
int synctex_test_sheet_2();
int synctex_test_sheet_3();
int synctex_test_form();
#endif
#ifdef __cplusplus
}
#endif
#endif

View file

@ -5,7 +5,7 @@ This file is part of the SyncTeX package.
Latest Revision: Tue Jun 14 08:23:30 UTC 2011
Version: 1.16
Version: 1.18
See synctex_parser_readme.txt for more details

View file

@ -0,0 +1,246 @@
# __SyncTeX__
This file is part of the __SyncTeX__ package.
[//]: # (Version: 1.19)
[//]: # (Date: Fri Jul 14 16:20:41 UTC 2017)
## Important
* Changes in version `1.19`
A long standing bug affecting only pdftex has been fixed by adding support to pdf forms. As a side effect, the synchronization algorithm gains in accuracy for all the engines, especially from pdf to source. Of course, there is a small cost in both memory footprint and computational time, but none is noticeable.
Some technical changes in the API.
* more consistent type naming convention
* `_s` suffix for struct's
* `_p` suffix for pointers
* `_t` suffix for standard types
* `_f` suffix for functions...
thus `synctex_node_t` has become `synctex_node_p`.
* supplemental argument in `synctex_display_query`. Set `page_hint` to the currently displayed pdf page number (0 based). If this info is not available, set `page_hint` to 0, it corresponds to the old behaviour.
* rename `synctex_next_result` to `synctex_scanner_next_result`
* additional `synctex_parser_private.h` header where
more API are exposed. For an advanced usage only (eg parallel synchronizations).
* `SYNCTEX_NO_UPDATER` preprocessor macro to deactivate some code useless to frontends.
## What is it ?
The *Synchronization TeXnology* named __SyncTeX__ is a new feature
of recent __TeX__ engines designed by Jérôme Laurens.
It allows to synchronize between input and output, which means to
navigate from the source document to the typeset material and vice versa.
Browse the source code for more information.
## Contents
This package is mainly for developers, it contains the following files:
* `synctex_parser_readme.md` (this file)
* `synctex_parser_version.txt`
* `synctex_parser_utils.c`
* `synctex_parser_utils.h`
* `synctex_parser_local.h`
* `synctex_parser.h`
* `synctex_parser_advanced.h`
* `synctex_parser.c`
The file you are reading contains more informations about the __SyncTeX__ parser history.
## Source
All stable sources are available from [TeXLive repository](http://www.tug.org/svn/texlive/trunk/Build/source/texk/web2c/synctexdir/).
Latest development sources are available from GitHub.
Please notice that due to the complexity of the TeXLive TeX distribution, there might be some delay before synchronization occurs between various repositories.
## Usage
In order to support __SyncTeX__ in a viewer, it is sufficient to include
in the source the files `synctex_parser.c` and `synctex_parser_utils.c`.
The synctex parser usage is described in `synctex_parser.h` header file.
More advanced usage is found in `synctex_parser_advanced.h`
The other files are used by tex engines or by the synctex command line utility:
```
ChangeLog
README.txt
am
man1
man5
synctex-common.h
synctex-convert.sh
synctex-e-mem.ch0
synctex-e-mem.ch1
synctex-e-rec.ch0
synctex-e-rec.ch1
synctex-etex.h
synctex-mem.ch0
synctex-mem.ch1
synctex-mem.ch2
synctex-pdf-rec.ch2
synctex-pdftex.h
synctex-rec.ch0
synctex-rec.ch1
synctex-rec.ch2
synctex-tex.h
synctex-xe-mem.ch2
synctex-xe-rec.ch2
synctex-xe-rec.ch3
synctex-xetex.h
synctex.c
synctex.defines
synctex.h
synctex_main.c
tests
...
```
## Version:
This is version 1, which refers to the synctex output file format.
The files are identified by a build number.
In order to help developers to automatically manage the version and build numbers
and download the parser only when necessary, the `synctex_parser_version.txt`
is an ASCII text file just containing the current version and build numbers eg `1.19`.
## History:
* 1.1: Thu Jul 17 09:28:13 UTC 2008
- First official version available in TeXLive 2008 DVD.
Unfortunately, the backwards synchronization is not working properly mainly for ConTeXt users, see below.
* 1.2: Tue Sep 2 10:28:32 UTC 2008
- Correction for ConTeXt support in the edit query.
The previous method was assuming that TeX boxes do not overlap,
which is reasonable for LaTeX but not for ConTeXt.
This assumption is no longer considered.
* 1.3: Fri Sep 5 09:39:57 UTC 2008
- Local variable "read" renamed to "already_read" to avoid conflicts.
- "inline" compiler directive renamed to "SYNCTEX_INLINE" for code support and maintenance
- _synctex_error cannot be inlined due to variable arguments (thanks Christiaan Hofman)
- Correction in the display query, extra boundary nodes are used for a more precise forwards synchronization
* 1.4: Fri Sep 12 08:12:34 UTC 2008
- For an unknown reason, the previous version was not the real 1.3 (as used in iTeXMac2 build 747).
As a consequence, a crash was observed.
- Some typos are fixed.
* 1.6: Mon Nov 3 20:20:02 UTC 2008
- The bug that prevented synchronization with compressed files on windows has been fixed.
- New interface to allow system specific customization.
- Note that some APIs have changed.
* 1.8: Mer 8 jul 2009 11:32:38 UTC
Note that version 1.7 was delivered privately.
- bug fix: synctex was causing a memory leak in pdftex and xetex, thus some processing speed degradation
- bug fix: the synctex command line tool was broken when updating a .synctex file
- enhancement: better accuracy of the synchronization process
- enhancement: the pdf output file and the associated .synctex file no longer need to live in the same directory.
The new -d option of the synctex command line tool manages this situation.
This is handy when using something like tex -output-directory=DIR ...
* 1.9: Wed Nov 4 11:52:35 UTC 2009
- Various typo fixed
- OutputDebugString replaced by OutputDebugStringA to deliberately disable unicode preprocessing
- New conditional created because OutputDebugStringA is only available since Windows 2K professional
* 1.10: Sun Jan 10 10:12:32 UTC 2010
- Bug fix in synctex_parser.c to solve a synchronization problem with amsmath's gather environment.
Concerns the synctex tool.
* 1.11: Sun Jan 17 09:12:31 UTC 2010
- Bug fix in synctex_parser.c, function synctex_node_box_visible_v: 'x' replaced by 'y'.
Only 3rd party tools are concerned.
* 1.12: Mon Jul 19 21:52:10 UTC 2010
- Bug fix in synctex_parser.c, function __synctex_open: the io_mode was modified even in case of a non zero return,
causing a void .synctex.gz file to be created even if it was not expected. Reported by Marek Kasik concerning a bug on evince.
* 1.13: Fri Mar 11 07:39:12 UTC 2011
- Bug fix in synctex_parser.c, better synchronization as suggested by Jan Sundermeyer (near line 3388).
- Stronger code design in synctex_parser_utils.c, function _synctex_get_name (really neutral behavior).
Only 3rd party tools are concerned.
* 1.14: Fri Apr 15 19:10:57 UTC 2011
- taking output_directory into account
- Replaced FOPEN_WBIN_MODE by FOPEN_W_MODE when opening the text version of the .synctex file.
- Merging with LuaTeX's version of synctex.c
* 1.15: Fri Jun 10 14:10:17 UTC 2011
This concerns the synctex command line tool and 3rd party developers.
TeX and friends are not concerned by these changes.
- Bug fixed in _synctex_get_io_mode_name, sometimes the wrong mode was returned
- Support for LuaTeX convention of './' file prefixing
* 1.16: Tue Jun 14 08:23:30 UTC 2011
This concerns the synctex command line tool and 3rd party developers.
TeX and friends are not concerned by these changes.
- Better forward search (thanks Jose Alliste)
- Support for LuaTeX convention of './' file prefixing now for everyone, not only for Windows
* 1.17: Fri Oct 14 08:15:16 UTC 2011
This concerns the synctex command line tool and 3rd party developers.
TeX and friends are not concerned by these changes.
- synctex_parser.c: cosmetic changes to enhance code readability
- Better forward synchronization.
The problem occurs for example with LaTeX \item command.
The fact is that this command creates nodes at parse time but these nodes are used only
after the text material of the \item is displayed on the page. The consequence is that sometimes,
forward synchronization spots an irrelevant point from the point of view of the editing process.
This was due to some very basic filtering policy, where a somehow arbitrary choice was made when
many different possibilities where offered for synchronisation.
Now, forward synchronization prefers nodes inside an hbox with as many acceptable spots as possible.
This is achieved with the notion of mean line and node weight.
- Adding support for the new file naming convention with './'
- function `synctex_ignore_leading_dot_slash_in_path replaces` `synctex_ignore_leading_dot_slash`
- function `_synctex_is_equivalent_file_name` is more permissive
Previously, the function synctex_scanner_get_tag would give an answer only when
the given file name was EXACTLY one of the file names listed in the synctex file.
The we added some changes accepting for example 'foo.tex' instead of './foo.tex'.
Now we have an even looser policy for dealing with file names.
If the given file name does not match exactly one the file names of the synctex file,
then we try to match the base names. If there is only one match of the base names,
then it is taken as a match for the whole names.
The base name is defined as following:
`./foo => foo
/my///.////foo => foo
/foo => /foo
/my//.foo => /my//.foo`
* 1.17: Tue Mar 13 10:10:03 UTC 2012
- minor changes, no version changes
- syntax man pages are fixed as suggested by M. Shimata
see mail to tex-live@tug.org titled "syntax.5 has many warnings from groff" and "syntax.1 use invalid macro for mdoc"
- 1.17: Tue Jan 14 09:55:00 UTC 2014, fixed a segfault, patch from Sebastian Ramacher
- 1.17: Mon Aug 04, fixed a memory leak
* 1.18: Thu Jun 25 11:36:05 UTC 2015
- nested sheets now fully supported (does it make sense in TeX)
- cosmetic changes: uniform indentation
- suppression of warnings, mainly long/int ones. In short, zlib likes ints when size_t likes longs.
- CLI synctex tool can build out of TeXLive (modulo appropriate options passed to the compiler)
* 1.19: Mon Jul 3 20:03:56 UTC 2017
- the nested sheets patch was not a good solution.
It has been moved from the parser to the engine.
See the `synctex.c` source file for detailed explanations.
- there is a new synctex format specification.
We can see that a `.synctex` file can contain many times
the same vertical position because many objects belong
to the same line. When the options read `-synctex=±2` or more,
a very basic compression algorithm is used:
if synctex is about to write the same number then it writes
an `=` sign instead. This saves approximately 10% of the
synctex output file, either compressed or not.
The new synctex parser has been updated accordingly.
Actual tex frontend won't see any difference with the
TeX engines that include this new feature.
Frontends with the new parser won't see any difference
with the older TeX engines.
Frontends with the new parser will only see a difference
with new TeX engines if `-synctex=±2` or more is used.
## Acknowledgments:
The author received useful remarks from the __pdfTeX__ developers, especially Hahn The Thanh,
and significant help from __XeTeX__ developer Jonathan Kew.
## Nota Bene:
If you include or use a significant part of the __SyncTeX__ package into a software,
I would appreciate to be listed as contributor and see __SyncTeX__" highlighted.
Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr

View file

@ -1,141 +0,0 @@
This file is part of the SyncTeX package.
The Synchronization TeXnology named SyncTeX is a new feature
of recent TeX engines designed by Jerome Laurens.
It allows to synchronize between input and output, which means to
navigate from the source document to the typeset material and vice versa.
More informations on http://itexmac2.sourceforge.net/SyncTeX.html
This package is mainly for developers, it mainly contains the following files:
synctex_parser_readme.txt
synctex_parser_version.txt
synctex_parser_utils.c
synctex_parser_utils.h
synctex_parser_local.h
synctex_parser.h
synctex_parser.c
The file you are reading contains more informations about the SyncTeX parser history.
In order to support SyncTeX in a viewer, it is sufficient to include
in the source the files synctex_parser.h and synctex_parser.c.
The synctex parser usage is described in synctex_parser.h header file.
The other files are used by tex engines or by the synctex command line utility:
ChangeLog
README.txt
am
man1
man5
synctex-common.h
synctex-convert.sh
synctex-e-mem.ch0
synctex-e-mem.ch1
synctex-e-rec.ch0
synctex-e-rec.ch1
synctex-etex.h
synctex-mem.ch0
synctex-mem.ch1
synctex-mem.ch2
synctex-pdf-rec.ch2
synctex-pdftex.h
synctex-rec.ch0
synctex-rec.ch1
synctex-rec.ch2
synctex-tex.h
synctex-xe-mem.ch2
synctex-xe-rec.ch2
synctex-xe-rec.ch3
synctex-xetex.h
synctex.c
synctex.defines
synctex.h
synctex_main.c
tests
Version:
--------
This is version 1, which refers to the synctex output file format.
The files are identified by a build number.
In order to help developers to automatically manage the version and build numbers
and download the parser only when necessary, the synctex_parser.version
is an ASCII text file just containing the current version and build numbers.
History:
--------
1.1: Thu Jul 17 09:28:13 UTC 2008
- First official version available in TeXLive 2008 DVD.
Unfortunately, the backwards synchronization is not working properly mainly for ConTeXt users, see below.
1.2: Tue Sep 2 10:28:32 UTC 2008
- Correction for ConTeXt support in the edit query.
The previous method was assuming that TeX boxes do not overlap,
which is reasonable for LaTeX but not for ConTeXt.
This assumption is no longer considered.
1.3: Fri Sep 5 09:39:57 UTC 2008
- Local variable "read" renamed to "already_read" to avoid conflicts.
- "inline" compiler directive renamed to "SYNCTEX_INLINE" for code support and maintenance
- _synctex_error cannot be inlined due to variable arguments (thanks Christiaan Hofman)
- Correction in the display query, extra boundary nodes are used for a more precise forwards synchronization
1.4: Fri Sep 12 08:12:34 UTC 2008
- For an unknown reason, the previous version was not the real 1.3 (as used in iTeXMac2 build 747).
As a consequence, a crash was observed.
- Some typos are fixed.
1.6: Mon Nov 3 20:20:02 UTC 2008
- The bug that prevented synchronization with compressed files on windows has been fixed.
- New interface to allow system specific customization.
- Note that some APIs have changed.
1.8: Mer 8 jul 2009 11:32:38 UTC
Note that version 1.7 was delivered privately.
- bug fix: synctex was causing a memory leak in pdftex and xetex, thus some processing speed degradation
- bug fix: the synctex command line tool was broken when updating a .synctex file
- enhancement: better accuracy of the synchronization process
- enhancement: the pdf output file and the associated .synctex file no longer need to live in the same directory.
The new -d option of the synctex command line tool manages this situation.
This is handy when using something like tex -output-directory=DIR ...
1.9: Wed Nov 4 11:52:35 UTC 2009
- Various typo fixed
- OutputDebugString replaced by OutputDebugStringA to deliberately disable unicode preprocessing
- New conditional created because OutputDebugStringA is only available since Windows 2K professional
1.10: Sun Jan 10 10:12:32 UTC 2010
- Bug fix in synctex_parser.c to solve a synchronization problem with amsmath's gather environment.
Concerns the synctex tool.
1.11: Sun Jan 17 09:12:31 UTC 2010
- Bug fix in synctex_parser.c, function synctex_node_box_visible_v: 'x' replaced by 'y'.
Only 3rd party tools are concerned.
1.12: Mon Jul 19 21:52:10 UTC 2010
- Bug fix in synctex_parser.c, function __synctex_open: the io_mode was modified even in case of a non zero return,
causing a void .synctex.gz file to be created even if it was not expected. Reported by Marek Kasik concerning a bug on evince.
1.13: Fri Mar 11 07:39:12 UTC 2011
- Bug fix in synctex_parser.c, better synchronization as suggested by Jan Sundermeyer (near line 3388).
- Stronger code design in synctex_parser_utils.c, function _synctex_get_name (really neutral behavior).
Only 3rd party tools are concerned.
1.14: Fri Apr 15 19:10:57 UTC 2011
- taking output_directory into account
- Replaced FOPEN_WBIN_MODE by FOPEN_W_MODE when opening the text version of the .synctex file.
- Merging with LuaTeX's version of synctex.c
1.15: Fri Jun 10 14:10:17 UTC 2011
This concerns the synctex command line tool and 3rd party developers.
TeX and friends are not concerned by these changes.
- Bug fixed in _synctex_get_io_mode_name, sometimes the wrong mode was returned
- Support for LuaTeX convention of './' file prefixing
1.16: Tue Jun 14 08:23:30 UTC 2011
This concerns the synctex command line tool and 3rd party developers.
TeX and friends are not concerned by these changes.
- Better forward search (thanks Jose Alliste)
- Support for LuaTeX convention of './' file prefixing now for everyone, not only for Windows
Acknowledgments:
----------------
The author received useful remarks from the pdfTeX developers, especially Hahn The Thanh,
and significant help from XeTeX developer Jonathan Kew
Nota Bene:
----------
If you include or use a significant part of the synctex package into a software,
I would appreciate to be listed as contributor and see "SyncTeX" highlighted.
Copyright (c) 2008-2011 jerome DOT laurens AT u-bourgogne DOT fr

View file

@ -1,41 +1,40 @@
/*
Copyright (c) 2008, 2009, 2010 , 2011 jerome DOT laurens AT u-bourgogne DOT fr
This file is part of the SyncTeX package.
Latest Revision: Tue Jun 14 08:23:30 UTC 2011
Version: 1.16
See synctex_parser_readme.txt for more details
License:
--------
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE
Except as contained in this notice, the name of the copyright holder
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization from the copyright holder.
Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr
This file is part of the __SyncTeX__ package.
[//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017)
[//]: # (Version: 1.19)
See `synctex_parser_readme.md` for more details
## License
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE
Except as contained in this notice, the name of the copyright holder
shall not be used in advertising or otherwise to promote the sale,
use or other dealings in this Software without prior written
authorization from the copyright holder.
*/
@ -57,27 +56,41 @@ authorization from the copyright holder.
#define SYNCTEX_WINDOWS 1
#endif
#ifdef _WIN32_WINNT_WINXP
#if defined(__OS2__)
#define SYNCTEX_OS2 1
#endif
#if defined(_WIN32)
#define SYNCTEX_RECENT_WINDOWS 1
#endif
#ifdef SYNCTEX_WINDOWS
#include <windows.h>
#include <shlwapi.h> /* Use shlwapi.lib */
#endif
void *_synctex_malloc(size_t size) {
void * ptr = malloc(size);
if(ptr) {
/* There used to be a switch to use bzero because it is more secure. JL */
memset(ptr,0, size);
}
return (void *)ptr;
void * ptr = malloc(size);
if(ptr) {
memset(ptr,0, size);/* ensures null termination of strings */
}
return (void *)ptr;
}
int _synctex_error(const char * reason,...) {
va_list arg;
void _synctex_free(void * ptr) {
if (ptr) {
free(ptr);
}
}
#if !defined(_WIN32)
# include <syslog.h>
#endif
int _synctex_log(int level, const char * prompt, const char * reason, ...) SYNCTEX_PRINTF_FORMAT(3, 4);
int _synctex_log(int level, const char * prompt, const char * reason, ...) {
va_list arg;
int result;
va_start (arg, reason);
# ifdef SYNCTEX_RECENT_WINDOWS
{/* This code is contributed by William Blum.
As it does not work on some older computers,
@ -89,11 +102,11 @@ int _synctex_error(const char * reason,...) {
JL.*/
char *buff;
size_t len;
OutputDebugStringA("SyncTeX ERROR: ");
OutputDebugStringA(prompt);
# ifdef _MSC_VER
len = _vscprintf(reason, arg) + 1;
buff = (char*)malloc( len * sizeof(char) );
#else /* MinGW */
# else /* MinGW */
size_t buffersize = 1024;
size_t max_buffersize = 1024 * buffersize;
int result;
@ -109,26 +122,77 @@ int _synctex_error(const char * reason,...) {
free(buff);
return -1;
}
#endif
result = vsprintf(buff, reason, arg) +strlen("SyncTeX ERROR: ");
# endif
result = vsprintf(buff, reason, arg) +strlen(prompt);
OutputDebugStringA(buff);
OutputDebugStringA("\n");
free(buff);
}
# elif defined SYNCTEX_USE_SYSLOG
char * buffer1 = NULL;
char * buffer2 = NULL;
openlog ("SyncTeX", LOG_CONS | LOG_PID | LOG_PERROR | LOG_NDELAY, LOG_LOCAL0);
if (vasprintf(&buffer1,reason,arg)>=0
&& asprintf(&buffer2,"%s%s",prompt, buffer1)>=0) {
syslog (level, "%s", buffer2);
result = (int)strlen(buffer2);
} else {
syslog (level, "%s",prompt);
vsyslog(level,reason,arg);
result = (int)strlen(prompt);
}
free(buffer1);
free(buffer2);
closelog();
# else
result = fprintf(stderr,"SyncTeX ERROR: ");
result += vfprintf(stderr, reason, arg);
result += fprintf(stderr,"\n");
FILE * where = level == LOG_ERR? stderr: stdout;
result = fputs(prompt,where);
result += vfprintf(where, reason, arg);
result += fprintf(where,"\n");
# endif
va_end (arg);
return result;
}
int _synctex_error(const char * reason,...) {
va_list arg;
int result;
va_start (arg, reason);
#if defined(SYNCTEX_RECENT_WINDOWS) /* LOG_ERR is not used */
result = _synctex_log(0, "! SyncTeX Error : ", reason, arg);
#else
result = _synctex_log(LOG_ERR, "! SyncTeX Error : ", reason, arg);
#endif
va_end (arg);
return result;
}
int _synctex_debug(const char * reason,...) {
va_list arg;
int result;
va_start (arg, reason);
#if defined(SYNCTEX_RECENT_WINDOWS) /* LOG_DEBUG is not used */
result = _synctex_log(0, "! SyncTeX Error : ", reason, arg);
#else
result = _synctex_log(LOG_DEBUG, "! SyncTeX Error : ", reason, arg);
#endif
va_end (arg);
return result;
}
/* strip the last extension of the given string, this string is modified! */
void _synctex_strip_last_path_extension(char * string) {
if(NULL != string){
char * last_component = NULL;
char * last_extension = NULL;
# if defined(SYNCTEX_WINDOWS)
last_component = PathFindFileName(string);
last_extension = PathFindExtension(string);
if(last_extension == NULL)return;
if(last_component == NULL)last_component = string;
if(last_extension>last_component){/* filter out paths like "my/dir/.hidden" */
last_extension[0] = '\0';
}
# else
char * next = NULL;
/* first we find the last path component */
if(NULL == (last_component = strstr(string,"/"))){
@ -139,12 +203,12 @@ void _synctex_strip_last_path_extension(char * string) {
last_component = next+1;
}
}
# ifdef SYNCTEX_WINDOWS
/* On Windows, the '\' is also a path separator. */
# if defined(SYNCTEX_OS2)
/* On OS2, the '\' is also a path separator. */
while((next = strstr(last_component,"\\"))){
last_component = next+1;
}
# endif
# endif /* SYNCTEX_OS2 */
/* then we find the last path extension */
if((last_extension = strstr(last_component,"."))){
++last_extension;
@ -156,39 +220,61 @@ void _synctex_strip_last_path_extension(char * string) {
last_extension[0] = '\0';
}
}
# endif /* SYNCTEX_WINDOWS */
}
}
const char * synctex_ignore_leading_dot_slash(const char * name)
synctex_bool_t synctex_ignore_leading_dot_slash_in_path(const char ** name_ref)
{
while(SYNCTEX_IS_DOT(*name) && SYNCTEX_IS_PATH_SEPARATOR(name[1])) {
name += 2;
while (SYNCTEX_IS_PATH_SEPARATOR(*name)) {
++name;
}
if (SYNCTEX_IS_DOT((*name_ref)[0]) && SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[1])) {
do {
(*name_ref) += 2;
while (SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[0])) {
++(*name_ref);
}
} while(SYNCTEX_IS_DOT((*name_ref)[0]) && SYNCTEX_IS_PATH_SEPARATOR((*name_ref)[1]));
return synctex_YES;
}
return name;
return synctex_NO;
}
/* The base name is necessary to deal with the 2011 file naming convention...
* path is a '\0' terminated string
* The return value is the trailing part of the argument,
* just following the first occurrence of the regexp pattern "[^|/|\].[\|/]+".*/
const char * _synctex_base_name(const char *path) {
const char * ptr = path;
do {
if (synctex_ignore_leading_dot_slash_in_path(&ptr)) {
return ptr;
}
do {
if (!*(++ptr)) {
return path;
}
} while (!SYNCTEX_IS_PATH_SEPARATOR(*ptr));
} while (*(++ptr));
return path;
}
/* Compare two file names, windows is sometimes case insensitive... */
synctex_bool_t _synctex_is_equivalent_file_name(const char *lhs, const char *rhs) {
/* Remove the leading regex '(\./+)*' in both rhs and lhs */
lhs = synctex_ignore_leading_dot_slash(lhs);
rhs = synctex_ignore_leading_dot_slash(rhs);
# ifdef SYNCTEX_WINDOWS
/* On Windows, filename should be compared case insensitive.
* The characters '/' and '\' are both valid path separators.
* There will be a very serious problem concerning UTF8 because
* not all the characters must be toupper...
* I would like to have URL's instead of filenames. */
synctex_ignore_leading_dot_slash_in_path(&lhs);
synctex_ignore_leading_dot_slash_in_path(&rhs);
next_character:
if(SYNCTEX_IS_PATH_SEPARATOR(*lhs)) {/* lhs points to a path separator */
if(!SYNCTEX_IS_PATH_SEPARATOR(*rhs)) {/* but not rhs */
if (SYNCTEX_IS_PATH_SEPARATOR(*lhs)) {/* lhs points to a path separator */
if (!SYNCTEX_IS_PATH_SEPARATOR(*rhs)) {/* but not rhs */
return synctex_NO;
}
} else if(SYNCTEX_IS_PATH_SEPARATOR(*rhs)) {/* rhs points to a path separator but not lhs */
++lhs;
++rhs;
synctex_ignore_leading_dot_slash_in_path(&lhs);
synctex_ignore_leading_dot_slash_in_path(&rhs);
goto next_character;
} else if (SYNCTEX_IS_PATH_SEPARATOR(*rhs)) {/* rhs points to a path separator but not lhs */
return synctex_NO;
} else if(toupper(*lhs) != toupper(*rhs)){/* uppercase do not match */
} else if (SYNCTEX_ARE_PATH_CHARACTERS_EQUAL(*lhs,*rhs)){/* uppercase do not match */
return synctex_NO;
} else if (!*lhs) {/* lhs is at the end of the string */
return *rhs ? synctex_NO : synctex_YES;
@ -198,25 +284,13 @@ next_character:
++lhs;
++rhs;
goto next_character;
# else
if (lhs[0] == '/' && rhs[0] == '/') { /* for absolute paths compare the real paths */
char *lhsreal = realpath(lhs, 0);
char *rhsreal = realpath(rhs, 0);
synctex_bool_t result = lhsreal && rhsreal && 0 == strcmp(lhsreal,rhsreal)?synctex_YES:synctex_NO;
free (lhsreal);
free (rhsreal);
return result;
} else {
return 0 == strcmp(lhs,rhs)?synctex_YES:synctex_NO;
}
# endif
}
synctex_bool_t _synctex_path_is_absolute(const char * name) {
if(!strlen(name)) {
return synctex_NO;
}
# ifdef SYNCTEX_WINDOWS
# if defined(SYNCTEX_WINDOWS) || defined(SYNCTEX_OS2)
if(strlen(name)>2) {
return (name[1]==':' && SYNCTEX_IS_PATH_SEPARATOR(name[2]))?synctex_YES:synctex_NO;
}
@ -244,8 +318,8 @@ const char * _synctex_last_path_component(const char * name) {
}
int _synctex_copy_with_quoting_last_path_component(const char * src, char ** dest_ref, size_t size) {
const char * lpc;
if(src && dest_ref) {
const char * lpc;
# define dest (*dest_ref)
dest = NULL; /* Default behavior: no change and sucess. */
lpc = _synctex_last_path_component(src);
@ -390,7 +464,6 @@ int _synctex_get_name(const char * output, const char * build_directory, char **
if(NULL == (dir_name = (char *)malloc(size+1))) {
_synctex_error("! _synctex_get_name: Memory problem");
free(core_name);
dir_name = NULL;
return -1;
}
if(dir_name != strncpy(dir_name,output,size)) {
@ -491,6 +564,17 @@ int _synctex_get_name(const char * output, const char * build_directory, char **
# undef CLEAN_AND_REMOVE
/* set up the returned values */
* synctex_name_ref = synctex_name;
/* synctex_name won't always end in .gz, even when compressed. */
FILE * F = fopen(synctex_name, "r");
if (F != NULL) {
if (!feof(F)
&& 31 == fgetc(F)
&& !feof(F)
&& 139 == fgetc(F)) {
io_mode = synctex_compress_mode_gz;
}
fclose(F);
}
* io_mode_ref = io_mode;
return 0;
}

View file

@ -1,16 +1,15 @@
/*
Copyright (c) 2008, 2009, 2010, 2011 jerome DOT laurens AT u-bourgogne DOT fr
Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr
This file is part of the __SyncTeX__ package.
[//]: # (Latest Revision: Fri Jul 14 16:20:41 UTC 2017)
[//]: # (Version: 1.19)
See `synctex_parser_readme.md` for more details
## License
This file is part of the SyncTeX package.
Latest Revision: Tue Jun 14 08:23:30 UTC 2011
Version: 1.16
See synctex_parser_readme.txt for more details
License:
--------
Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
@ -39,16 +38,20 @@ authorization from the copyright holder.
*/
#ifndef SYNCTEX_PARSER_UTILS_H
#define SYNCTEX_PARSER_UTILS_H
/* The utilities declared here are subject to conditional implementation.
* All the operating system special stuff goes here.
* The problem mainly comes from file name management: path separator, encoding...
*/
# define synctex_bool_t int
# define synctex_YES -1
typedef int synctex_bool_t;
# define synctex_YES (0==0)
# define synctex_NO (0==1)
# define synctex_ADD_QUOTES -1
# define synctex_COMPRESS -1
# define synctex_NO 0
# define synctex_DONT_ADD_QUOTES 0
# define synctex_DONT_COMPRESS 0
@ -61,32 +64,45 @@ authorization from the copyright holder.
extern "C" {
#endif
# ifdef _WIN32
# if defined(_WIN32) || defined(__OS2__)
# define SYNCTEX_CASE_SENSITIVE_PATH 0
# define SYNCTEX_IS_PATH_SEPARATOR(c) ('/' == c || '\\' == c)
# else
# define SYNCTEX_CASE_SENSITIVE_PATH 1
# define SYNCTEX_IS_PATH_SEPARATOR(c) ('/' == c)
# endif
# ifdef _WIN32
# if defined(_WIN32) || defined(__OS2__)
# define SYNCTEX_IS_DOT(c) ('.' == c)
# else
# define SYNCTEX_IS_DOT(c) ('.' == c)
# endif
# if SYNCTEX_CASE_SENSITIVE_PATH
# define SYNCTEX_ARE_PATH_CHARACTERS_EQUAL(left,right) (left != right)
# else
# define SYNCTEX_ARE_PATH_CHARACTERS_EQUAL(left,right) (toupper(left) != toupper(right))
# endif
# ifdef __GNUC__
# define SYNCTEX_PRINTF_FORMAT(si, ftc) __attribute__ ((format (printf, si, ftc)))
# else
# define SYNCTEX_PRINTF_FORMAT(si, ftc)
# endif
/* This custom malloc functions initializes to 0 the newly allocated memory.
* There is no bzero function on windows. */
void *_synctex_malloc(size_t size);
/* To balance _synctex_malloc.
* ptr might be NULL. */
void _synctex_free(void * ptr);
/* This is used to log some informational message to the standard error stream.
* On Windows, the stderr stream is not exposed and another method is used.
* The return value is the number of characters printed. */
int _synctex_error(const char * reason,...) SYNCTEX_PRINTF_FORMAT(1, 2);
int _synctex_error(const char * reason,...) SYNCTEX_PRINTF_FORMAT(1, 2);
int _synctex_debug(const char * reason,...) SYNCTEX_PRINTF_FORMAT(1, 2);
/* strip the last extension of the given string, this string is modified!
* This function depends on the OS because the path separator may differ.
@ -106,6 +122,9 @@ synctex_bool_t _synctex_path_is_absolute(const char * name);
/* Description forthcoming...*/
const char * _synctex_last_path_component(const char * name);
/* Description forthcoming...*/
const char * _synctex_base_name(const char *path);
/* If the core of the last path component of src is not already enclosed with double quotes ('"')
* and contains a space character (' '), then a new buffer is created, the src is copied and quotes are added.
* In all other cases, no destination buffer is created and the src is not copied.
@ -138,10 +157,11 @@ int _synctex_get_name(const char * output, const char * build_directory, char **
/* returns the correct mode required by fopen and gzopen from the given io_mode */
const char * _synctex_get_io_mode_name(synctex_io_mode_t io_mode);
const char * synctex_ignore_leading_dot_slash(const char * name);
synctex_bool_t synctex_ignore_leading_dot_slash_in_path(const char ** name);
#ifdef __cplusplus
}
#endif
#endif
#endif /* SYNCTEX_PARSER_UTILS_H */

View file

@ -1 +1 @@
1.16
1.19