add lisp packages

This commit is contained in:
2020-12-05 21:29:49 +01:00
parent 85e20365ae
commit a6e2395755
7272 changed files with 1363243 additions and 0 deletions

25
lisp/pdf-tools/build/server/.gitignore vendored Normal file
View File

@@ -0,0 +1,25 @@
*.o
.deps/
Makefile
Makefile.in
aclocal.m4
autom4te.cache/
config.h
config.h.in
config.log
config.status
configure
depcomp
epdfinfo
install-sh
libsynctex.a
missing
stamp-h1
ar-lib
compile
config.h.in~
.clang_complete
callgrind.out.*
config.guess
config.sub
TAGS

View File

@@ -0,0 +1,44 @@
bin_PROGRAMS = epdfinfo
epdfinfo_CFLAGS = -Wall $(glib_CFLAGS) $(poppler_glib_CFLAGS) $(poppler_CFLAGS) \
$(png_CFLAGS)
epdfinfo_CXXFLAGS = -Wall $(epdfinfo_CFLAGS)
epdfinfo_LDADD = $(glib_LIBS) $(poppler_glib_LIBS) $(poppler_LIBS) \
$(png_LIBS) libsynctex.a $(zlib_LIBS)
epdfinfo_SOURCES = epdfinfo.c epdfinfo.h poppler-hack.cc
noinst_LIBRARIES = libsynctex.a
libsynctex_a_SOURCES = synctex_parser.c synctex_parser_utils.c synctex_parser.h \
synctex_parser_local.h synctex_parser_utils.h
libsynctex_a_CFLAGS = -w $(zlib_CFLAGS) -DSYNCTEX_USE_LOCAL_HEADER
if HAVE_W32
epdfinfo_LDADD += -lshlwapi
endif
SYNCTEX_UPSTREAM = svn://tug.org/texlive/trunk/Build/source/texk/web2c/synctexdir
SYNCTEX_FILES = synctex_parser.c \
synctex_parser.h \
synctex_parser_readme.txt \
synctex_parser_utils.c \
synctex_parser_utils.h \
synctex_parser_version.txt \
synctex_version.h \
synctex_parser_advanced.h
check-local:
@if $(MAKE) --version 2>&1 | grep -q GNU; then \
cd test && $(MAKE) $(AM_MAKEFLAGS); \
else \
echo "Skipping tests in server/test (requires GNU make)"; \
fi
synctex-pull:
@if [ -n "$$(git status --porcelain)" ]; then \
git status; \
echo "Not checking-out files into a dirty work-directory"; \
false; \
fi
for file in $(SYNCTEX_FILES); do \
svn export --force $(SYNCTEX_UPSTREAM)/$$file; \
done

View File

@@ -0,0 +1,545 @@
#!/bin/sh
##
## Installs package dependencies and builds the application.
##
# Don't exit if some command fails.
set +e
# Disable file globbing.
set -f
# Boolean variables are true if non-empty and false otherwise.
# Command to install packages.
PKGCMD=
# Args to pass to $PKGCMD.
PKGARGS=
# Required packages.
PACKAGES=
# Whether package installation requires root permissions.
PKG_INSTALL_AS_ROOT=true
# Whether to skip package installation altogether.
PKG_INSTALL_SKIP=
# Whether to force package installation, even if it does not seem
# necessary.
PKG_INSTALL_FORCE=
# Only test if the OS is handled by this script.
DRY_RUN=
# If and where to install the program.
INSTALL_DIR=
# Whether we can install packages.
OS_IS_HANDLED=true
# Which OSs installer to use
OS=
## +-----------------------------------------------------------+
## * Utility Functions
## +-----------------------------------------------------------+
usage()
{
cat <<EOF
usage:$(basename "$0") [--help|-n|-i DIR|[-d -D]|[--os OS]]
-n Don't do anything, but check if this OS is handled.
-i DIR Install the program in the given directory.
-d Force dependency installattion.
-D Skip dependency installattion.
--os OS Use the given OS's installer
--help Display this message.
EOF
exit "$1"
}
# Search for command $1 in PATH. Print its absolute filename.
which()
{
if [ -z "$1" ]; then
return 1
fi
IFS=:
for dir in $PATH; do
if [ -x "$dir/$1" ]; then
printf "%s" "$dir/$1"
unset IFS
return 0
fi
done
unset IFS
return 1
}
# Quote $@ for the shell.
quote()
{
quoted=
for arg; do
qarg=$(printf "%s" "$arg" | sed -e 's/[|&;<>()$\`"'\'' ]/\\&/g')
if [ -z "$quoted" ]; then
quoted=$qarg
else
quoted="$quoted $qarg"
fi
done
printf "%s" "$quoted"
}
# Attempt to exec $@ as root.
exec_privileged() {
if [ -z "$1" ]; then
echo "internal error: command is empty"
exit 2
fi
if [ -w / ]; then
"$@"
elif which sudo >/dev/null 2>&1; then
sudo -- "$@"
retval=$?
sudo -k
return $retval
elif which su >/dev/null 2>&1; then
su -c "$(quote "$@")"
else
echo "No such program: sudo or su"
exit 1
fi
}
# Test if $1 is in PATH or exit with a failure status.
assert_program()
{
if ! which "$1" >/dev/null 2>&1; then
echo "No such program: $1"
exit 1
fi
}
# Source filename $1 and echo variable $2.
source_var()
{
if ! [ -f "$1" ] || ! [ -r "$1" ] || [ -z "$2" ]; then
return 1
fi
# shellcheck source=/dev/null
. "$1"
eval "printf '%s\n' \$$2"
return 0
}
exit_success()
{
echo "==========================="
echo " Build succeeded. :O) "
echo "==========================="
exit 0
}
exit_fail()
{
echo "==========================="
echo " Build failed. ;o( "
echo "==========================="
if [ -z "$PKG_INSTALL_FORCE" ]; then
echo "Note: maybe try the '-d' option."
fi
exit 1
}
# Return 0, if all required packages seem to be installed.
have_packages_installed()
{
{
which pkg-config || return 1
if ! [ -f configure ];then
which autoreconf || return 1
which automake || return 1
fi
for lib in libpng glib-2.0 poppler poppler-glib zlib; do
pkg-config --exists $lib || return 1
done
which make || return 1
which gcc || which cc || return 1
which g++ || which c++ || return 1
cc $(pkg-config --cflags poppler) -o /dev/null -E - 2>/dev/null <<EOF
#include <PDFDocEncoding.h>
EOF
[ $? -eq 0 ] || return 1
return 0
} >/dev/null 2>&1
}
handle_options()
{
while [ $# -gt 0 ]; do
case $1 in
--help) usage 0;;
-n) DRY_RUN=true;;
-d) PKG_INSTALL_FORCE=true ;;
-D) PKG_INSTALL_SKIP=true ;;
-i)
shift
[ $# -gt 0 ] || usage 1
if [ "${1%%/}" != "${PWD%%/}" ]; then
INSTALL_DIR=$1
fi ;;
--os)
shift
[ $# -gt 0 ] || usage 1
OS="$1"
;;
*) usage 1 ;;
esac
shift
done
if [ -n "$PKG_INSTALL_SKIP" ] && [ -n "$PKG_INSTALL_FORCE" ]; then
usage 1
fi
}
## +-----------------------------------------------------------+
## * OS Functions
## +-----------------------------------------------------------+
# Archlinux
os_arch() {
if ! [ -e "/etc/arch-release" ]; then
return 1;
fi
PKGCMD=pacman
PKGARGS="-S --needed"
PACKAGES="base-devel libpng zlib poppler-glib"
return 0;
}
# CentOS
os_centos() {
if ! [ -e "/etc/centos-release" ]; then
return 1
fi
PKGCMD=yum
if yum help install-n >/dev/null 2>&1; then
PKGARGS=install-n
else
PKGARGS=install
fi
PACKAGES="autoconf
automake
gcc
gcc-c++
libpng-devel
make
pkgconfig
poppler-devel
poppler-glib-devel
zlib-devel"
return 0
}
# FreeBSD
os_freebsd() {
if ! which uname >/dev/null 2>&1 || [ "$(uname -s)" != "FreeBSD" ]; then
return 1
fi
PKGCMD=pkg
PKGARGS=install
PACKAGES="autotools poppler-glib png pkgconf"
return 0
}
# OpenBSD
os_openbsd() {
if ! which uname >/dev/null 2>&1 || [ "$(uname -s)" != "OpenBSD" ]; then
return 1
fi
PKGCMD=pkg_add
PKGARGS="-uU"
PACKAGES="autoconf-2.69p2 automake-1.15.1 poppler poppler-utils png"
export AUTOCONF_VERSION=2.69
export AUTOMAKE_VERSION=1.15
if whereis clang++ ;then
export CXX=clang++
elif whereis eg++ ;then
export CXX=eg++
else
export CXX=eg++
PACKAGES="${PACKAGES} g++"
fi
export CXXFLAGS="-std=c++11 -I/usr/local/include/poppler -I/usr/local/include"
return 0
}
# Fedora
os_fedora() {
if ! [ -e "/etc/fedora-release" ]; then
return 1
fi
PKGCMD=dnf
PKGARGS=install
PACKAGES="autoconf
automake
gcc
gcc-c++
libpng-devel
make
poppler-devel
poppler-glib-devel
zlib-devel"
VERSION=$(source_var /etc/os-release VERSION_ID)
if [ -n "$VERSION" ] && [ "$VERSION" -ge 26 ]; then
PACKAGES="$PACKAGES pkgconf"
else
PACKAGES="$PACKAGES pkgconfig"
fi
return 0
}
# Debian/Ubuntu
os_debian() {
if ! [ -e "/etc/debian_version" ]; then
return 1
fi
PACKAGES="autoconf
automake
g++
gcc
libpng-dev
libpoppler-dev
libpoppler-glib-dev
libpoppler-private-dev
libz-dev
make
pkg-config"
PKGCMD=apt-get
PKGARGS=install
return 0
}
# Msys2
os_msys2() {
if [ -z "$MSYSTEM" ] || ! [ -r "/etc/profile" ]; then
return 1
fi
case $MSYSTEM in
MINGW64)
PACKAGES="base-devel
mingw-w64-x86_64-libpng
mingw-w64-x86_64-poppler
mingw-w64-x86_64-toolchain
mingw-w64-x86_64-zlib" ;;
MINGW32)
PACKAGES="base-devel
mingw-w64-i686-libpng
mingw-w64-i686-poppler
mingw-w64-i686-toolchain
mingw-w64-i686-zlib" ;;
MSYS)
case $(uname -m) in
x86_64)
MSYSTEM=MINGW64 ;;
*)
MSYSTEM=MINGW32 ;;
esac
export MSYSTEM
# shellcheck source=/dev/null
. /etc/profile
eval "exec $(quote "$0" "$@")" ;;
*)
echo "Unrecognized MSYSTEM value: $MSYSTEM"
exit 1 ;;
esac
PKGCMD=pacman
PKGARGS="-S --needed"
PKG_INSTALL_AS_ROOT=
return 0
}
# MacOS
os_macos() {
if ! which uname >/dev/null 2>&1 || [ "$(uname -s)" != "Darwin" ]; then
return 1
elif which brew >/dev/null 2>&1; then
PKGCMD=brew
PKGARGS=install
PACKAGES="pkg-config poppler automake"
PKG_INSTALL_AS_ROOT=
# homebrew install libffi as keg-only, meaning we need to set
# PKG_CONFIG_PATH manually so configure can find it
export PKG_CONFIG_PATH="$(brew --prefix libffi)/lib/pkgconfig/"
elif which port >/dev/null 2>&1; then
PKGCMD=port
PKGARGS=install
PACKAGES="pkgconfig poppler automake libpng"
else
return 1
fi
return 0
}
# NixOS
os_nixos() {
# Already in the nix-shell.
if [ -n "$AUTOBUILD_NIX_SHELL" ]; then
return 0
fi
if ! which nix-shell >/dev/null 2>&1; then
return 1
fi
if [ -n "$DRY_RUN" ]; then
return 0
fi
command="AUTOBUILD_NIX_SHELL=true"
command="$command;export AUTOBUILD_NIX_SHELL"
command="$command;$(quote "$0" "$@")"
exec nix-shell --pure --command "$command" \
-p gcc gnumake automake autoconf pkgconfig libpng zlib poppler
}
# Gentoo
os_gentoo() {
if ! [ -e "/etc/gentoo-release" ]; then
return 1
fi
PKGCMD=emerge
PKGARGS=--noreplace
PACKAGES="app-text/poppler
dev-util/pkgconfig
media-libs/libpng
sys-devel/autoconf
sys-devel/automake
sys-devel/gcc
sys-devel/make
sys-libs/zlib"
return 0
}
# By Parameter --os
os_argument() {
[ -z "$OS" ] && return 1
case $OS in
macos) os_macos "$@";;
freebsd) os_freebsd "$@";;
arch) os_arch "$@";;
centos) os_centos "$@";;
openbsd) os_openbsd "$@";;
fedora) os_fedora "$@";;
debian) os_debian "$@";;
gentoo) os_gentoo "$@";;
msys2) os_msys2 "$@";;
nixos) os_nixos "$@";;
*) echo "Invalid --os argument: $OS"
exit 1
esac || {
echo "Unable to install on this system as $OS"
exit 1
}
}
## +-----------------------------------------------------------+
## * Figure out were we are, install deps and build the program
## +-----------------------------------------------------------+
handle_options "$@"
os_argument "$@" || \
os_macos "$@" || \
os_freebsd "$@" || \
os_arch "$@" || \
os_centos "$@" || \
os_openbsd "$@" || \
os_fedora "$@" || \
os_debian "$@" || \
os_gentoo "$@" || \
os_msys2 "$@" || \
os_nixos "$@" || \
{
OS_IS_HANDLED=
if [ -z "$DRY_RUN" ]; then
echo "Failed to recognize this system, trying to continue."
fi
}
if [ -n "$DRY_RUN" ]; then
[ -n "$OS_IS_HANDLED" ]
exit $?
fi
if [ -n "$PKGCMD" ];then
echo "---------------------------"
echo " Installing packages "
echo "---------------------------"
if [ -n "$PKG_INSTALL_SKIP" ]; then
echo "Skipping package installation (as requested)"
elif [ -z "$PKG_INSTALL_FORCE" ] && have_packages_installed; then
echo "Skipping package installation (already installed)"
else
assert_program "$PKGCMD"
echo "$PKGCMD $PKGARGS $PACKAGES"
if [ -n "$PKG_INSTALL_AS_ROOT" ]; then
exec_privileged $PKGCMD $PKGARGS $PACKAGES
else
$PKGCMD $PKGARGS $PACKAGES
fi
fi
echo
fi
echo "---------------------------"
echo " Configuring and compiling "
echo "---------------------------"
# Try to be in the correct directory.
if which dirname >/dev/null 2>&1; then
cd "$(dirname "$0")" || {
echo "Failed to change into the source directory"
exit 1
}
fi
# Create the configure script.
if ! [ -f ./configure ]; then
assert_program autoreconf
echo "autoreconf -i"
autoreconf -i
[ -f ./configure ] || exit_fail
fi
# Build the program.
if [ -n "$INSTALL_DIR" ]; then
prefix=--bindir=$INSTALL_DIR
fi
echo "./configure -q $prefix && make -s"
eval "./configure -q $(quote "$prefix") && make -s || exit_fail"
echo
if [ -n "$INSTALL_DIR" ]; then
echo "---------------------------"
echo " Installing "
echo "---------------------------"
echo make -s install
if mkdir -p -- "$INSTALL_DIR" && [ -w "$INSTALL_DIR" ]; then
make install || exit_fail
else
exec_privileged make install || exit_fail
fi
# Copy dynamic libraries on windows.
if [ -f epdfinfo.exe ]; then
assert_program awk
assert_program ldd
for dll in $(ldd epdfinfo.exe | awk '/\/mingw/ {print $3}'); do
cp -u "$dll" "$INSTALL_DIR"
done
fi
echo
fi
exit_success
# Local Variables:
# compile-command: "shellcheck autobuild"
# End:

View File

@@ -0,0 +1,5 @@
#!/bin/sh
echo "Running autoreconf..."
autoreconf -i

View File

@@ -0,0 +1,113 @@
# -*- Autoconf -*-
# Process this file with autoconf to produce a configure script.
AC_PREREQ([2.67])
AC_INIT([epdfinfo], 1.0, [politza@fh-trier.de])
AM_INIT_AUTOMAKE([-Wall -Wno-override foreign silent-rules])
AC_CONFIG_SRCDIR([epdfinfo.h])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AC_PROG_CC
AM_PROG_CC_C_O
AC_PROG_CXX
AC_PROG_RANLIB
AM_PROG_AR
# Checks for libraries.
HAVE_POPPLER_FIND_OPTS="no (requires poppler-glib >= 0.22)"
HAVE_POPPLER_ANNOT_WRITE="no (requires poppler-glib >= 0.19.4)"
HAVE_POPPLER_ANNOT_MARKUP="no (requires poppler-glib >= 0.26)"
PKG_CHECK_MODULES([png], [libpng])
PKG_CHECK_MODULES([glib], [glib-2.0])
PKG_CHECK_MODULES([poppler], [poppler])
PKG_CHECK_MODULES([poppler_glib], [poppler-glib >= 0.16.0])
PKG_CHECK_EXISTS([poppler-glib >= 0.19.4], [HAVE_POPPLER_ANNOT_WRITE=yes])
PKG_CHECK_EXISTS([poppler-glib >= 0.22], [HAVE_POPPLER_FIND_OPTS=yes])
PKG_CHECK_EXISTS([poppler-glib >= 0.26], [HAVE_POPPLER_ANNOT_MARKUP=yes])
PKG_CHECK_MODULES([zlib], [zlib])
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[
#ifndef _WIN32
error
#endif
]])], [have_w32=true], [have_w32=false])
AM_CONDITIONAL(HAVE_W32, [test "$have_w32" = true])
if test "$have_w32" = true; then
if test "$MSYSTEM" = MINGW32 -o "$MSYSTEM" = MINGW64; then
# glib won't work properly on msys2 without it.
CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $CFLAGS"
fi
fi
SAVED_CPPFLAGS=$CPPFLAGS
CPPFLAGS=$poppler_CFLAGS
AC_LANG_PUSH([C++])
# Check if we can use the -std=c++11 option.
m4_include([m4/ax_check_compile_flag.m4])
AX_CHECK_COMPILE_FLAG([-std=c++11], [HAVE_STD_CXX11=yes])
if test "$HAVE_STD_CXX11" = yes; then
CXXFLAGS="-std=c++11 $CXXFLAGS"
fi
# Check for private poppler header.
AC_CHECK_HEADERS([Annot.h PDFDocEncoding.h], [],
AC_MSG_ERROR([cannot find necessary poppler-private header (see README.org)]))
AC_LANG_POP([C++])
CPPFLAGS=$SAVED_CPPFLAGS
# Setup compile time features.
if test "$HAVE_POPPLER_FIND_OPTS" = yes; then
AC_DEFINE([HAVE_POPPLER_FIND_OPTS],1,
[Define to 1 to enable case sensitive searching (requires poppler-glib >= 0.22).])
fi
if test "$HAVE_POPPLER_ANNOT_WRITE" = yes; then
AC_DEFINE([HAVE_POPPLER_ANNOT_WRITE],1,
[Define to 1 to enable writing of annotations (requires poppler-glib >= 0.19.4).])
fi
if test "$HAVE_POPPLER_ANNOT_MARKUP" = yes; then
AC_DEFINE([HAVE_POPPLER_ANNOT_MARKUP],1,
[Define to 1 to enable adding of markup annotations (requires poppler-glib >= 0.26).])
fi
AC_CANONICAL_HOST
# Checks for header files.
AC_CHECK_HEADERS([stdlib.h string.h strings.h err.h])
AC_MSG_CHECKING([for error.h])
SAVED_CFLAGS=$CFLAGS
CFLAGS="$poppler_CFLAGS $poppler_glib_CFLAGS"
AC_LANG_PUSH([C])
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
#include <error.h>
],[error (0, 0, "");])],
[AC_DEFINE([HAVE_ERROR_H],1, [Define to 1 if error.h is usable.])
AC_MSG_RESULT([yes])],
AC_MSG_RESULT([no]))
AC_LANG_POP([C])
CFLAGS=$SAVED_CFLAGS
# Checks for typedefs, structures, and compiler characteristics.
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
AC_CHECK_TYPES([ptrdiff_t])
AC_C_BIGENDIAN
# Checks for library functions.
AC_FUNC_ERROR_AT_LINE
AC_FUNC_STRTOD
AC_CHECK_FUNCS([strcspn strtol getline])
AC_CONFIG_FILES([Makefile])
AC_OUTPUT
echo
echo "Is case-sensitive searching enabled ? ${HAVE_POPPLER_FIND_OPTS}"
echo "Is modifying text annotations enabled ? ${HAVE_POPPLER_ANNOT_WRITE}"
echo "Is modifying markup annotations enabled ? ${HAVE_POPPLER_ANNOT_MARKUP}"
echo

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,252 @@
// Copyright (C) 2013, 2014 Andreas Politz
// Author: Andreas Politz <politza@fh-trier.de>
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#ifndef _EPDF_H_
#define _EPDF_H_ _EPDF_H_
#include "config.h"
#include <glib.h>
#include <poppler.h>
#include <png.h>
/* Some library functions print warnings to stdout, inhibit it. */
#define DISCARD_STDOUT(saved_fd) \
do { \
int __fd; \
fflush(stdout); \
saved_fd = dup(1); \
__fd = open("/dev/null", O_WRONLY); \
dup2(__fd, 1); \
close(__fd); \
} while (0)
#define UNDISCARD_STDOUT(saved_fd) \
do { \
fflush(stdout); \
dup2(saved_fd, 1); \
close(saved_fd); \
} while (0)
/* Writing responses */
#define OK_BEGIN() \
do { \
puts("OK"); \
} while (0)
#define OK_END() \
do { \
puts("."); \
fflush (stdout); \
} while (0)
#define OK() \
do { \
puts ("OK\n."); \
fflush (stdout); \
} while (0)
/* Dealing with image data. */
#ifdef WORDS_BIGENDIAN
#define ARGB_TO_RGB(rgb, argb) \
do { \
rgb[0] = argb[1]; \
rgb[1] = argb[2]; \
rgb[2] = argb[3]; \
} while (0)
#define ARGB_EQUAL(argb1, argb2) \
(argb1[1] == argb2[1] \
&& argb1[2] == argb2[2] \
&& argb1[3] == argb2[3])
#else
#define ARGB_TO_RGB(rgb, argb) \
do { \
rgb[0] = argb[2]; \
rgb[1] = argb[1]; \
rgb[2] = argb[0]; \
} while (0)
#define ARGB_EQUAL(argb1, argb2) \
(argb1[0] == argb2[0] \
&& argb1[1] == argb2[1] \
&& argb1[2] == argb2[2])
#endif
#define NORMALIZE_PAGE_ARG(doc, first, last) \
*first = MAX(1, *first); \
if (*last <= 0) \
*last = poppler_document_get_n_pages (doc); \
else \
*last = MIN(*last, poppler_document_get_n_pages (doc));
/* png_jmpbuf is supposed to be not available in older versions of
libpng. */
#ifndef png_jmpbuf
# define png_jmpbuf(png_ptr) ((png_ptr)->jmpbuf)
#endif
#ifndef HAVE_ERROR_H
# define error(status, errno, fmt, args...) \
do { \
int error = (errno); \
fflush (stdout); \
fprintf (stderr, "%s: " fmt, PACKAGE_NAME, ## args); \
if (error) \
fprintf (stderr, ": %s", strerror (error)); \
fprintf (stderr, "\n"); \
exit (status); \
} while (0)
#endif
#define internal_error(fmt, args...) \
error (2, 0, "internal error in %s: " fmt, __func__, ## args)
#define error_if_not(expr) \
if (! (expr)) goto error;
#define perror_if_not(expr, fmt, args...) \
do { \
if (! (expr)) \
{ \
printf_error_response ((fmt), ## args); \
goto error; \
} \
} while (0)
#define cerror_if_not(expr, error_msg, fmt, args...) \
do { \
if (! (expr)) \
{ \
if (error_msg) \
*(error_msg) = g_strdup_printf((fmt), ## args); \
goto error; \
} \
} while (0)
/* Declare commands */
#define DEC_CMD(name) \
{#name, cmd_ ## name, cmd_ ## name ## _spec, \
G_N_ELEMENTS (cmd_ ## name ## _spec)}
#define DEC_CMD2(command, name) \
{name, cmd_ ## command, cmd_ ## command ## _spec, \
G_N_ELEMENTS (cmd_ ## command ## _spec)}
/* Declare option */
#define DEC_DOPT(name, type, sname) \
{name, type, offsetof (document_options_t, sname)}
enum suffix_char { NONE, COLON, NEWLINE};
enum image_type { PPM, PNG };
typedef struct
{
PopplerAnnotMapping *amap;
gchar *key;
} annotation_t;
typedef enum
{
ARG_INVALID = 0,
ARG_DOC,
ARG_BOOL,
ARG_STRING,
ARG_NONEMPTY_STRING,
ARG_NATNUM,
ARG_EDGE,
ARG_EDGE_OR_NEGATIVE,
ARG_EDGES,
ARG_EDGES_OR_POSITION,
ARG_COLOR,
ARG_REST
} command_arg_type_t;
typedef struct
{
const char *name;
command_arg_type_t type;
size_t offset;
} document_option_t;
typedef struct
{
PopplerColor bg, fg;
gboolean usecolors;
gboolean printed;
} render_options_t;
typedef struct
{
render_options_t render;
} document_options_t;
typedef struct
{
PopplerDocument *pdf;
char *filename;
char *passwd;
struct
{
GHashTable *keys; /* key => page */
GList **pages; /* page array */
} annotations;
document_options_t options;
} document_t;
typedef struct
{
command_arg_type_t type;
union
{
gboolean flag;
const char *string;
long natnum;
document_t *doc;
gdouble edge;
PopplerColor color;
PopplerRectangle rectangle;
#ifdef HAVE_POPPLER_ANNOT_MARKUP
PopplerQuadrilateral quadrilateral;
#endif
struct
{
char * const *args;
int nargs;
} rest;
} value;
} command_arg_t;
typedef struct
{
GHashTable *documents;
} epdfinfo_t;
typedef struct
{
const char *name;
void (* execute) (const epdfinfo_t *ctxt, const command_arg_t *args);
const command_arg_type_t *args_spec;
int nargs;
} command_t;
/* Defined in poppler-hack.cc */
#ifdef HAVE_POPPLER_ANNOT_WRITE
extern void xpoppler_annot_set_rectangle (PopplerAnnot*, PopplerRectangle*);
#endif
extern gchar *xpoppler_annot_markup_get_created (PopplerAnnotMarkup*);
#endif /* _EPDF_H_ */

View File

@@ -0,0 +1,74 @@
# ===========================================================================
# https://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
# ===========================================================================
#
# SYNOPSIS
#
# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
#
# DESCRIPTION
#
# Check whether the given FLAG works with the current language's compiler
# or gives an error. (Warnings, however, are ignored)
#
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
# success/failure.
#
# If EXTRA-FLAGS is defined, it is added to the current language's default
# flags (e.g. CFLAGS) when the check is done. The check is thus made with
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
# force the compiler to issue an error when a bad flag is given.
#
# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
#
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
#
# LICENSE
#
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
# Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program. If not, see <https://www.gnu.org/licenses/>.
#
# As a special exception, the respective Autoconf Macro's copyright owner
# gives unlimited permission to copy, distribute and modify the configure
# scripts that are the output of Autoconf when processing the Macro. You
# need not follow the terms of the GNU General Public License when using
# or distributing such scripts, even though portions of the text of the
# Macro appear in them. The GNU General Public License (GPL) does govern
# all other use of the material that constitutes the Autoconf Macro.
#
# This special exception to the GPL applies to versions of the Autoconf
# Macro released by the Autoconf Archive. When you make and distribute a
# modified version of the Autoconf Macro, you may extend this special
# exception to the GPL to apply to your modified version as well.
#serial 5
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
[AS_VAR_SET(CACHEVAR,[yes])],
[AS_VAR_SET(CACHEVAR,[no])])
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
AS_VAR_IF(CACHEVAR,yes,
[m4_default([$2], :)],
[m4_default([$3], :)])
AS_VAR_POPDEF([CACHEVAR])dnl
])dnl AX_CHECK_COMPILE_FLAGS

View File

@@ -0,0 +1,122 @@
// Copyright (C) 2013, 2014 Andreas Politz
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <config.h>
#include <PDFDocEncoding.h>
#include <Annot.h>
#include <glib.h>
#include <glib-object.h>
#include <poppler-features.h>
extern "C"
{
GType poppler_annot_get_type (void) G_GNUC_CONST;
GType poppler_annot_markup_get_type (void) G_GNUC_CONST;
#define POPPLER_TYPE_ANNOT (poppler_annot_get_type ())
#define POPPLER_ANNOT(obj) \
(G_TYPE_CHECK_INSTANCE_CAST ((obj), POPPLER_TYPE_ANNOT, PopplerAnnot))
#define POPPLER_IS_ANNOT_MARKUP(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), POPPLER_TYPE_ANNOT_MARKUP))
#define POPPLER_TYPE_ANNOT_MARKUP (poppler_annot_markup_get_type ())
#if POPPLER_CHECK_VERSION(0,72,0)
#define GET_CSTR c_str
#else
#define GET_CSTR getCString
#endif
struct PopplerAnnot
{
GObject parent_instance;
Annot *annot;
};
struct PopplerAnnotMarkup
{
GObject parent_instance;
};
struct PopplerRectangle
{
double x1;
double y1;
double x2;
double y2;
};
// This function does not modify its argument s, but for
// compatibility reasons (e.g. getLength in GooString.h before 2015)
// with older poppler code, it can't be declared as such.
char *_xpoppler_goo_string_to_utf8(/* const */ GooString *s)
{
char *result;
if (! s)
return NULL;
if (s->hasUnicodeMarker()) {
result = g_convert (s->GET_CSTR () + 2,
s->getLength () - 2,
"UTF-8", "UTF-16BE", NULL, NULL, NULL);
} else {
int len;
gunichar *ucs4_temp;
int i;
len = s->getLength ();
ucs4_temp = g_new (gunichar, len + 1);
for (i = 0; i < len; ++i) {
ucs4_temp[i] = pdfDocEncoding[(unsigned char)s->getChar(i)];
}
ucs4_temp[i] = 0;
result = g_ucs4_to_utf8 (ucs4_temp, -1, NULL, NULL, NULL);
g_free (ucs4_temp);
}
return result;
}
#ifdef HAVE_POPPLER_ANNOT_WRITE
// Set the rectangle of an annotation. It was first added in v0.26.
void xpoppler_annot_set_rectangle (PopplerAnnot *a, PopplerRectangle *rectangle)
{
GooString *state = (GooString*) a->annot->getAppearState ();
char *ustate = _xpoppler_goo_string_to_utf8 (state);
a->annot->setRect (rectangle->x1, rectangle->y1,
rectangle->x2, rectangle->y2);
a->annot->setAppearanceState (ustate);
g_free (ustate);
}
#endif
// This function is in the library, but the enforced date parsing is
// incomplete (at least in some versions), because it ignores the
// timezone.
gchar *xpoppler_annot_markup_get_created (PopplerAnnotMarkup *poppler_annot)
{
AnnotMarkup *annot;
GooString *text;
g_return_val_if_fail (POPPLER_IS_ANNOT_MARKUP (poppler_annot), NULL);
annot = static_cast<AnnotMarkup *>(POPPLER_ANNOT (poppler_annot)->annot);
text = (GooString*) annot->getDate ();
return text ? _xpoppler_goo_string_to_utf8 (text) : NULL;
}
}

View File

@@ -0,0 +1,12 @@
HAVE_POPPLER_ANNOT_WRITE
0.19.4 solves bug 49080, which potentially corrupts PDF files.
HAVE_POPPLER_FIND_OPTS
0.22 PopplerFindFlags
0.22 poppler_page_find_text_with_options
HAVE_POPPLER_ANNOT_SET_RECT
0.26 Adds function poppler_annot_set_rectangle
HAVE_POPPLER_ANNOT_MARKUP
0.26 poppler_annot_text_markup_new_{highlight,squiggly,strikeout,underline}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,429 @@
/*
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.21)
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__
# define __SYNCTEX_PARSER__
#include "synctex_version.h"
#ifdef __cplusplus
extern "C" {
#endif
/* 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
* - return: 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);
/**
* 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);
/**
* 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.
* For an hbox node, the mean line is the mean
* of all the lines of the child nodes.
* Sometimes, when synchronization form pdf to source
* fails with the line, one should try with the
* mean line.
*/
int synctex_node_tag(synctex_node_p node);
int synctex_node_line(synctex_node_p node);
int synctex_node_mean_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 page where the node appears.
* This is a 1 based index as given by TeX.
*/
int synctex_node_page(synctex_node_p node);
/**
* 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
}
#endif
#endif

View File

@@ -0,0 +1,554 @@
/*
Copyright (c) 2008-2017 jerome DOT laurens AT u-bourgogne DOT fr
This file is part of the __SyncTeX__ package.
[//]: # (Latest Revision: Sun Oct 15 15:09:55 UTC 2017)
[//]: # (Version: 1.21)
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 least.
*/
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,
/* handle */
synctex_data_handle_w_idx = 0,
synctex_data_handle_w_max = 1,
};
/* 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 referred 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_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(void);
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);
/**
* Whether 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

@@ -0,0 +1,3 @@
#include <stdio.h>
#define printf(fmt, args...) (fprintf (stderr, (fmt), ## args))
#define SYNCTEX_INLINE

View File

@@ -0,0 +1,204 @@
This file is part of the SyncTeX package.
Please refer to synctex_parser_readme.md
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 information 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_private.h
synctex_parser.h
synctex_parser.c
The file you are reading contains more information 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
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, 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: Thu Mar 9 21:26:27 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 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-2014 jerome DOT laurens AT u-bourgogne DOT fr

View File

@@ -0,0 +1,570 @@
/*
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.21)
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.
*/
/* In this file, we find all the functions that may depend on the operating system. */
#include <synctex_parser_utils.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
#include <string.h>
#include <sys/stat.h>
#if defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__)
#define SYNCTEX_WINDOWS 1
#endif
#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) {
memset(ptr,0, size);/* ensures null termination of strings */
}
return (void *)ptr;
}
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,va_list arg) {
int result;
# ifdef SYNCTEX_RECENT_WINDOWS
{/* This code is contributed by William Blum.
As it does not work on some older computers,
the _WIN32 conditional here is replaced with a SYNCTEX_RECENT_WINDOWS one.
According to http://msdn.microsoft.com/en-us/library/aa363362(VS.85).aspx
Minimum supported client Windows 2000 Professional
Minimum supported server Windows 2000 Server
People running Windows 2K standard edition will not have OutputDebugStringA.
JL.*/
char *buff;
size_t len;
OutputDebugStringA(prompt);
len = _vscprintf(reason, arg) + 1;
buff = (char*)malloc( len * sizeof(char) );
result = vsprintf(buff, reason, arg) +strlen(prompt);
OutputDebugStringA(buff);
OutputDebugStringA("\n");
free(buff);
}
# elif 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
FILE * where = level == LOG_ERR? stderr: stdout;
result = fputs(prompt,where);
result += vfprintf(where, reason, arg);
result += fprintf(where,"\n");
# endif
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,"/"))){
last_component = string;
} else {
++last_component;
while((next = strstr(last_component,"/"))){
last_component = next+1;
}
}
# if defined(SYNCTEX_OS2)
/* On OS2, the '\' is also a path separator. */
while((next = strstr(last_component,"\\"))){
last_component = next+1;
}
# endif /* SYNCTEX_OS2 */
/* then we find the last path extension */
if((last_extension = strstr(last_component,"."))){
++last_extension;
while((next = strstr(last_extension,"."))){
last_extension = next+1;
}
--last_extension;/* back to the "." */
if(last_extension>last_component){/* filter out paths like ....my/dir/.hidden"*/
last_extension[0] = '\0';
}
}
# endif /* SYNCTEX_WINDOWS */
}
}
synctex_bool_t synctex_ignore_leading_dot_slash_in_path(const char ** name_ref)
{
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 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 */
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 */
return synctex_NO;
}
++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 (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;
} else if(!*rhs) {/* rhs is at the end of the string but not lhs */
return synctex_NO;
}
++lhs;
++rhs;
goto next_character;
}
synctex_bool_t _synctex_path_is_absolute(const char * name) {
if(!strlen(name)) {
return synctex_NO;
}
# if defined(SYNCTEX_WINDOWS) || defined(SYNCTEX_OS2)
if(strlen(name)>2) {
return (name[1]==':' && SYNCTEX_IS_PATH_SEPARATOR(name[2]))?synctex_YES:synctex_NO;
}
return synctex_NO;
# else
return SYNCTEX_IS_PATH_SEPARATOR(name[0])?synctex_YES:synctex_NO;
# endif
}
/* We do not take care of UTF-8 */
const char * _synctex_last_path_component(const char * name) {
const char * c = name+strlen(name);
if(c>name) {
if(!SYNCTEX_IS_PATH_SEPARATOR(*c)) {
do {
--c;
if(SYNCTEX_IS_PATH_SEPARATOR(*c)) {
return c+1;
}
} while(c>name);
}
return c;/* the last path component is the void string*/
}
return c;
}
int _synctex_copy_with_quoting_last_path_component(const char * src, char ** dest_ref, size_t size) {
if(src && dest_ref) {
const char * lpc;
# define dest (*dest_ref)
dest = NULL; /* Default behavior: no change and success. */
lpc = _synctex_last_path_component(src);
if(strlen(lpc)) {
if(strchr(lpc,' ') && lpc[0]!='"' && lpc[strlen(lpc)-1]!='"') {
/* We are in the situation where adding the quotes is allowed. */
/* Time to add the quotes. */
/* Consistency test: we must have dest+size>dest+strlen(dest)+2
* or equivalently: strlen(dest)+2<size (see below) */
if(strlen(src)<size) {
if((dest = (char *)malloc(size+2))) {
char * dpc = dest + (lpc-src); /* dpc is the last path component of dest. */
if(dest != strncpy(dest,src,size)) {
_synctex_error("! _synctex_copy_with_quoting_last_path_component: Copy problem");
free(dest);
dest = NULL;/* Don't forget to reinitialize. */
return -2;
}
memmove(dpc+1,dpc,strlen(dpc)+1); /* Also move the null terminating character. */
dpc[0]='"';
dpc[strlen(dpc)+1]='\0';/* Consistency test */
dpc[strlen(dpc)]='"';
return 0; /* Success. */
}
return -1; /* Memory allocation error. */
}
_synctex_error("! _synctex_copy_with_quoting_last_path_component: Internal inconsistency");
return -3;
}
return 0; /* Success. */
}
return 0; /* No last path component. */
# undef dest
}
return 1; /* Bad parameter, this value is subject to changes. */
}
/* The client is responsible of the management of the returned string, if any. */
char * _synctex_merge_strings(const char * first,...);
char * _synctex_merge_strings(const char * first,...) {
va_list arg;
size_t size = 0;
const char * temp;
/* First retrieve the size necessary to store the merged string */
va_start (arg, first);
temp = first;
do {
size_t len = strlen(temp);
if(UINT_MAX-len<size) {
_synctex_error("! _synctex_merge_strings: Capacity exceeded.");
return NULL;
}
size+=len;
} while( (temp = va_arg(arg, const char *)) != NULL);
va_end(arg);
if(size>0) {
char * result = NULL;
++size;
/* Create the memory storage */
if(NULL!=(result = (char *)malloc(size))) {
char * dest = result;
va_start (arg, first);
temp = first;
do {
if((size = strlen(temp))>0) {
/* There is something to merge */
if(dest != strncpy(dest,temp,size)) {
_synctex_error("! _synctex_merge_strings: Copy problem");
free(result);
result = NULL;
return NULL;
}
dest += size;
}
} while( (temp = va_arg(arg, const char *)) != NULL);
va_end(arg);
dest[0]='\0';/* Terminate the merged string */
return result;
}
_synctex_error("! _synctex_merge_strings: Memory problem");
return NULL;
}
return NULL;
}
/* 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.
*/
int _synctex_get_name(const char * output, const char * build_directory, char ** synctex_name_ref, synctex_io_mode_t * io_mode_ref)
{
if(output && synctex_name_ref && io_mode_ref) {
/* If output is already absolute, we just have to manage the quotes and the compress mode */
size_t size = 0;
char * synctex_name = NULL;
synctex_io_mode_t io_mode = *io_mode_ref;
const char * base_name = _synctex_last_path_component(output); /* do not free, output is the owner. base name of output*/
/* Do we have a real base name ? */
if(strlen(base_name)>0) {
/* Yes, we do. */
const char * temp = NULL;
char * core_name = NULL; /* base name of output without path extension. */
char * dir_name = NULL; /* dir name of output */
char * quoted_core_name = NULL;
char * basic_name = NULL;
char * gz_name = NULL;
char * quoted_name = NULL;
char * quoted_gz_name = NULL;
char * build_name = NULL;
char * build_gz_name = NULL;
char * build_quoted_name = NULL;
char * build_quoted_gz_name = NULL;
struct stat buf;
time_t the_time = 0;
/* Create core_name: let temp point to the dot before the path extension of base_name;
* We start form the \0 terminating character and scan the string upward until we find a dot.
* The leading dot is not accepted. */
if((temp = strrchr(base_name,'.')) && (size = temp - base_name)>0) {
/* There is a dot and it is not at the leading position */
if(NULL == (core_name = (char *)malloc(size+1))) {
_synctex_error("! _synctex_get_name: Memory problem 1");
return -1;
}
if(core_name != strncpy(core_name,base_name,size)) {
_synctex_error("! _synctex_get_name: Copy problem 1");
free(core_name);
dir_name = NULL;
return -2;
}
core_name[size] = '\0';
} else {
/* There is no path extension,
* Just make a copy of base_name */
core_name = _synctex_merge_strings(base_name);
}
/* core_name is properly set up, owned by "self". */
/* creating dir_name. */
size = strlen(output)-strlen(base_name);
if(size>0) {
/* output contains more than one path component */
if(NULL == (dir_name = (char *)malloc(size+1))) {
_synctex_error("! _synctex_get_name: Memory problem");
free(core_name);
return -1;
}
if(dir_name != strncpy(dir_name,output,size)) {
_synctex_error("! _synctex_get_name: Copy problem");
free(dir_name);
dir_name = NULL;
free(core_name);
dir_name = NULL;
return -2;
}
dir_name[size] = '\0';
}
/* dir_name is properly set up. It ends with a path separator, if non void. */
/* creating quoted_core_name. */
if(strchr(core_name,' ')) {
quoted_core_name = _synctex_merge_strings("\"",core_name,"\"");
}
/* quoted_core_name is properly set up. */
if(dir_name &&strlen(dir_name)>0) {
basic_name = _synctex_merge_strings(dir_name,core_name,synctex_suffix,NULL);
if(quoted_core_name && strlen(quoted_core_name)>0) {
quoted_name = _synctex_merge_strings(dir_name,quoted_core_name,synctex_suffix,NULL);
}
} else {
basic_name = _synctex_merge_strings(core_name,synctex_suffix,NULL);
if(quoted_core_name && strlen(quoted_core_name)>0) {
quoted_name = _synctex_merge_strings(quoted_core_name,synctex_suffix,NULL);
}
}
if(!_synctex_path_is_absolute(output) && build_directory && (size = strlen(build_directory))) {
temp = build_directory + size - 1;
if(_synctex_path_is_absolute(temp)) {
build_name = _synctex_merge_strings(build_directory,basic_name,NULL);
if(quoted_core_name && strlen(quoted_core_name)>0) {
build_quoted_name = _synctex_merge_strings(build_directory,quoted_name,NULL);
}
} else {
build_name = _synctex_merge_strings(build_directory,"/",basic_name,NULL);
if(quoted_core_name && strlen(quoted_core_name)>0) {
build_quoted_name = _synctex_merge_strings(build_directory,"/",quoted_name,NULL);
}
}
}
if(basic_name) {
gz_name = _synctex_merge_strings(basic_name,synctex_suffix_gz,NULL);
}
if(quoted_name) {
quoted_gz_name = _synctex_merge_strings(quoted_name,synctex_suffix_gz,NULL);
}
if(build_name) {
build_gz_name = _synctex_merge_strings(build_name,synctex_suffix_gz,NULL);
}
if(build_quoted_name) {
build_quoted_gz_name = _synctex_merge_strings(build_quoted_name,synctex_suffix_gz,NULL);
}
/* All the others names are properly set up... */
/* retain the most recently modified file */
# define TEST(FILENAME,COMPRESS_MODE) \
if(FILENAME) {\
if (stat(FILENAME, &buf)) { \
free(FILENAME);\
FILENAME = NULL;\
} else if (buf.st_mtime>the_time) { \
the_time=buf.st_mtime; \
synctex_name = FILENAME; \
if (COMPRESS_MODE) { \
io_mode |= synctex_io_gz_mask; \
} else { \
io_mode &= ~synctex_io_gz_mask; \
} \
} \
}
TEST(basic_name,synctex_DONT_COMPRESS);
TEST(gz_name,synctex_COMPRESS);
TEST(quoted_name,synctex_DONT_COMPRESS);
TEST(quoted_gz_name,synctex_COMPRESS);
TEST(build_name,synctex_DONT_COMPRESS);
TEST(build_gz_name,synctex_COMPRESS);
TEST(build_quoted_name,synctex_DONT_COMPRESS);
TEST(build_quoted_gz_name,synctex_COMPRESS);
# undef TEST
/* Free all the intermediate filenames, except the one that will be used as returned value. */
# define CLEAN_AND_REMOVE(FILENAME) \
if(FILENAME && (FILENAME!=synctex_name)) {\
remove(FILENAME);\
printf("synctex tool info: %s removed\n",FILENAME);\
free(FILENAME);\
FILENAME = NULL;\
}
CLEAN_AND_REMOVE(basic_name);
CLEAN_AND_REMOVE(gz_name);
CLEAN_AND_REMOVE(quoted_name);
CLEAN_AND_REMOVE(quoted_gz_name);
CLEAN_AND_REMOVE(build_name);
CLEAN_AND_REMOVE(build_gz_name);
CLEAN_AND_REMOVE(build_quoted_name);
CLEAN_AND_REMOVE(build_quoted_gz_name);
# 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;
}
return -1;/* bad argument */
}
return -2;
}
const char * _synctex_get_io_mode_name(synctex_io_mode_t io_mode) {
static const char * synctex_io_modes[4] = {"r","rb","a","ab"};
unsigned index = ((io_mode & synctex_io_gz_mask)?1:0) + ((io_mode & synctex_io_append_mask)?2:0);// bug pointed out by Jose Alliste
return synctex_io_modes[index];
}

View File

@@ -0,0 +1,163 @@
/*
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.21)
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.
*/
#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...
*/
#include "synctex_version.h"
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_DONT_ADD_QUOTES 0
# define synctex_DONT_COMPRESS 0
#ifndef __SYNCTEX_PARSER_UTILS__
# define __SYNCTEX_PARSER_UTILS__
#include <stdlib.h>
#ifdef __cplusplus
extern "C" {
#endif
# 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
# 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
/* 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,...);
int _synctex_debug(const char * reason,...);
/* strip the last extension of the given string, this string is modified!
* This function depends on the OS because the path separator may differ.
* This should be discussed more precisely. */
void _synctex_strip_last_path_extension(char * string);
/* Compare two file names, windows is sometimes case insensitive...
* The given strings may differ stricto sensu, but represent the same file name.
* It might not be the real way of doing things.
* The return value is an undefined non 0 value when the two file names are equivalent.
* It is 0 otherwise. */
synctex_bool_t _synctex_is_equivalent_file_name(const char *lhs, const char *rhs);
/* Description forthcoming.*/
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.
* 0 on success, which means no error, something non 0 means error, mainly due to memory allocation failure, or bad parameter.
* This is used to fix a bug in the first version of pdftex with synctex (1.40.9) for which names with spaces
* were not managed in a standard way.
* On success, the caller owns the buffer pointed to by dest_ref (is any) and
* is responsible of freeing the memory when done.
* The size argument is the size of the src buffer. On return the dest_ref points to a buffer sized size+2.*/
int _synctex_copy_with_quoting_last_path_component(const char * src, char ** dest_ref, size_t size);
/* These are the possible extensions of the synctex file */
extern const char * synctex_suffix;
extern const char * synctex_suffix_gz;
typedef unsigned int synctex_io_mode_t;
typedef enum {
synctex_io_append_mask = 1,
synctex_io_gz_mask = synctex_io_append_mask<<1
} synctex_io_mode_masks_t;
typedef enum {
synctex_compress_mode_none = 0,
synctex_compress_mode_gz = 1
} synctex_compress_mode_t;
int _synctex_get_name(const char * output, const char * build_directory, char ** synctex_name_ref, synctex_io_mode_t * io_mode_ref);
/* 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);
synctex_bool_t synctex_ignore_leading_dot_slash_in_path(const char ** name);
#ifdef __cplusplus
}
#endif
#endif
#endif /* SYNCTEX_PARSER_UTILS_H */

View File

@@ -0,0 +1 @@
1.21

View File

@@ -0,0 +1,59 @@
/*
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.21)
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_VERSION__
# define __SYNCTEX_VERSION__
# define SYNCTEX_VERSION_MAJOR 1
# define SYNCTEX_VERSION_STRING "1.21"
# define SYNCTEX_CLI_VERSION_STRING "1.5"
#endif

View File

@@ -0,0 +1,2 @@
*.Dockerfile
*.build

View File

@@ -0,0 +1,9 @@
#!/bin/sh
PATH="$(dirname "$0")":$PATH
set -e
yes-or-enter | ./autobuild -i /bin
yes-or-enter | ./autobuild -i /usr/bin | \
grep -q "Skipping package installation (already installed)"

View File

@@ -0,0 +1,9 @@
#!/bin/bash
# Step over prompts from the package-manager.
if [ -f /etc/arch-release ]; then
yes ''
else
yes
fi

View File

@@ -0,0 +1,4 @@
ADD . /epdfinfo
WORKDIR /epdfinfo
RUN make -s distclean || true
CMD ["sh", "./test/docker/lib/run-tests"]

View File

@@ -0,0 +1,6 @@
# -*- dockerfile -*-
FROM base/archlinux
RUN pacman -Syu --noconfirm --noprogressbar && \
pacman -S --noconfirm --noprogressbar poppler-glib base-devel

View File

@@ -0,0 +1,3 @@
# -*- dockerfile -*-
FROM centos:7
RUN yum update -y && yum install -y gcc gcc-c++ poppler-glib-devel

View File

@@ -0,0 +1,4 @@
# -*- dockerfile -*-
FROM debian:8
RUN apt-get update -y && apt-get install -y gcc g++ libpoppler-glib-dev

View File

@@ -0,0 +1,4 @@
# -*- dockerfile -*-
FROM debian:9
RUN apt-get update -y && apt-get install -y gcc g++ libpoppler-glib-dev

View File

@@ -0,0 +1,5 @@
# -*- dockerfile -*-
FROM fedora:24
RUN dnf update -y && dnf install -y gcc gcc-c++ poppler-glib-devel

View File

@@ -0,0 +1,5 @@
# -*- dockerfile -*-
FROM fedora:25
RUN dnf update -y && dnf install -y gcc gcc-c++ poppler-glib-devel

View File

@@ -0,0 +1,5 @@
# -*- dockerfile -*-
FROM fedora:26
RUN dnf update -y && dnf install -y gcc gcc-c++ poppler-glib-devel

View File

@@ -0,0 +1,5 @@
# -*- dockerfile -*-
FROM gentoo/stage3-amd64
RUN emerge --sync && emerge sys-devel/gcc app-text/poppler

View File

@@ -0,0 +1,4 @@
# -*- dockerfile -*-
FROM ubuntu:trusty
RUN apt-get update -y && apt-get install -y gcc g++ libpoppler-glib-dev

View File

@@ -0,0 +1,4 @@
# -*- dockerfile -*-
FROM ubuntu:xenial
RUN apt-get update -y && apt-get install -y gcc g++ libpoppler-glib-dev

View File

@@ -0,0 +1,4 @@
# -*- dockerfile -*-
FROM ubuntu:artful
RUN apt-get update -y && apt-get install -y gcc g++ libpoppler-glib-dev