diff --git a/source/libs/README b/source/libs/README index e2c11b34f..86518d988 100644 --- a/source/libs/README +++ b/source/libs/README @@ -28,7 +28,7 @@ graphite2 1.3.14 - checked 10apr20 https://sourceforge.net/projects/silgraphite/files/graphite2/ (requires C++11) -harfbuzz 8.5.0 - checked 14may24 +harfbuzz 9.0.0 - checked 27aug24 https://github.com/harfbuzz/harfbuzz/releases/latest icu 74.2 - checked 22dec23 @@ -37,7 +37,7 @@ icu 74.2 - checked 22dec23 libpaper 1.1.29 - checked 07jan24 https://ftp.debian.org/debian/pool/main/libp/libpaper/ -libpng 1.6.43 - checked 24feb24 +libpng 1.6.44 - checked 13sep24 https://sourceforge.net/projects/libpng/files/ - used by many lua 5.2.4 diff --git a/source/libs/libpng/ChangeLog b/source/libs/libpng/ChangeLog index ec0a78c51..4afa60052 100644 --- a/source/libs/libpng/ChangeLog +++ b/source/libs/libpng/ChangeLog @@ -1,3 +1,8 @@ +2024-09-13 Akira Kakuto + + Import libpng-1.6.44. + * version.ac: Adjust. + 2024-04-07 Karl Berry * configure.ac (AM_PROG_AR): include for cosmopolitan, from Luigi. diff --git a/source/libs/libpng/README b/source/libs/libpng/README index f4ae444eb..515904aea 100644 --- a/source/libs/libpng/README +++ b/source/libs/libpng/README @@ -1,4 +1,4 @@ - Building libpng-1.6.43 as part of the TL tree + Building libpng-1.6.44 as part of the TL tree ============================================= This directory libs/libpng/ uses a proxy Makefile.am to build the libpng library @@ -14,4 +14,4 @@ copied to libs/libpng/configure.ac. ============================= 2009-07-23 Peter Breitenlohner -2024-02-24 Akira Kakuto +2024-09-13 Akira Kakuto diff --git a/source/libs/libpng/TLpatches/ChangeLog b/source/libs/libpng/TLpatches/ChangeLog index 996e52a48..19136b0aa 100644 --- a/source/libs/libpng/TLpatches/ChangeLog +++ b/source/libs/libpng/TLpatches/ChangeLog @@ -1,3 +1,7 @@ +2024-09-13 Akira Kakuto + + Import libpng-1.6.44. + 2024-02-24 Akira Kakuto Import libpng-1.6.43. diff --git a/source/libs/libpng/TLpatches/TL-Changes b/source/libs/libpng/TLpatches/TL-Changes index f22fe37d3..20db4d347 100644 --- a/source/libs/libpng/TLpatches/TL-Changes +++ b/source/libs/libpng/TLpatches/TL-Changes @@ -1,5 +1,5 @@ -Changes applied to the libpng-1.6.43/ tree as obtained from: - https://sourceforge.net/projects/libpng/files/libpng16/1.6.43/ +Changes applied to the libpng-1.6.44/ tree as obtained from: + https://sourceforge.net/projects/libpng/files/libpng16/1.6.44/ Copied: scripts/pnglibconf.h.prebuilt -> pnglibconf.h diff --git a/source/libs/libpng/configure b/source/libs/libpng/configure index 6cb5a5c20..fc988d5d8 100755 --- a/source/libs/libpng/configure +++ b/source/libs/libpng/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.72 for libpng (TeX Live) 1.6.43. +# Generated by GNU Autoconf 2.72 for libpng (TeX Live) 1.6.44. # # Report bugs to . # @@ -604,8 +604,8 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='libpng (TeX Live)' PACKAGE_TARNAME='libpng--tex-live-' -PACKAGE_VERSION='1.6.43' -PACKAGE_STRING='libpng (TeX Live) 1.6.43' +PACKAGE_VERSION='1.6.44' +PACKAGE_STRING='libpng (TeX Live) 1.6.44' PACKAGE_BUGREPORT='tex-k@tug.org' PACKAGE_URL='' @@ -1342,7 +1342,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -'configure' configures libpng (TeX Live) 1.6.43 to adapt to many kinds of systems. +'configure' configures libpng (TeX Live) 1.6.44 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1414,7 +1414,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of libpng (TeX Live) 1.6.43:";; + short | recursive ) echo "Configuration of libpng (TeX Live) 1.6.44:";; esac cat <<\_ACEOF @@ -1534,7 +1534,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -libpng (TeX Live) configure 1.6.43 +libpng (TeX Live) configure 1.6.44 generated by GNU Autoconf 2.72 Copyright (C) 2023 Free Software Foundation, Inc. @@ -1861,7 +1861,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by libpng (TeX Live) $as_me 1.6.43, which was +It was created by libpng (TeX Live) $as_me 1.6.44, which was generated by GNU Autoconf 2.72. Invocation command line was $ $0$ac_configure_args_raw @@ -4822,7 +4822,7 @@ fi # Define the identity of the package. PACKAGE='libpng--tex-live-' - VERSION='1.6.43' + VERSION='1.6.44' printf "%s\n" "#define PACKAGE \"$PACKAGE\"" >>confdefs.h @@ -7996,7 +7996,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by libpng (TeX Live) $as_me 1.6.43, which was +This file was extended by libpng (TeX Live) $as_me 1.6.44, which was generated by GNU Autoconf 2.72. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -8064,7 +8064,7 @@ ac_cs_config_escaped=`printf "%s\n" "$ac_cs_config" | sed "s/^ //; s/'/'\\\\\\\\ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config='$ac_cs_config_escaped' ac_cs_version="\\ -libpng (TeX Live) config.status 1.6.43 +libpng (TeX Live) config.status 1.6.44 configured by $0, generated by GNU Autoconf 2.72, with options \\"\$ac_cs_config\\" diff --git a/source/libs/libpng/libpng-src/ANNOUNCE b/source/libs/libpng/libpng-src/ANNOUNCE index bc147adb7..a2a7ac363 100644 --- a/source/libs/libpng/libpng-src/ANNOUNCE +++ b/source/libs/libpng/libpng-src/ANNOUNCE @@ -1,5 +1,5 @@ -libpng 1.6.43 - February 23, 2024 -================================= +libpng 1.6.44 - September 12, 2024 +================================== This is a public release of libpng, intended for use in production code. @@ -9,13 +9,13 @@ Files available for download Source files with LF line endings (for Unix/Linux): - * libpng-1.6.43.tar.xz (LZMA-compressed, recommended) - * libpng-1.6.43.tar.gz (deflate-compressed) + * libpng-1.6.44.tar.xz (LZMA-compressed, recommended) + * libpng-1.6.44.tar.gz (deflate-compressed) Source files with CRLF line endings (for Windows): - * lpng1643.7z (LZMA-compressed, recommended) - * lpng1643.zip (deflate-compressed) + * lpng1644.7z (LZMA-compressed, recommended) + * lpng1644.zip (deflate-compressed) Other information: @@ -25,36 +25,29 @@ Other information: * TRADEMARK.md -Changes from version 1.6.42 to version 1.6.43 +Changes from version 1.6.43 to version 1.6.44 --------------------------------------------- - * Fixed the row width check in png_check_IHDR(). - This corrected a bug that was specific to the 16-bit platforms, - and removed a spurious compiler warning from the 64-bit builds. - (Reported by Jacek Caban; fixed by John Bowler) - * Added eXIf chunk support to the push-mode reader in pngpread.c. - (Contributed by Chris Blume) - * Added contrib/pngexif for the benefit of the users who would like - to inspect the content of eXIf chunks. - * Added contrib/conftest/basic.dfa, a basic build-time configuration. + * Hardened calculations in chroma handling to prevent overflows, and + relaxed a constraint in cHRM validation to accomodate the standard + ACES AP1 set of color primaries. (Contributed by John Bowler) - * Fixed a preprocessor condition in pngread.c that broke build-time - configurations like contrib/conftest/pngcp.dfa. - (Contributed by John Bowler) - * Added CMake build support for LoongArch LSX. - (Contributed by GuXiWei) - * Fixed a CMake build error that occurred under a peculiar state of the - dependency tree. This was a regression introduced in libpng-1.6.41. - (Contributed by Dan Rosser) - * Marked the installed libpng headers as system headers in CMake. - (Contributed by Benjamin Buch) - * Updated the build support for RISCOS. - (Contributed by Cameron Cawley) - * Updated the makefiles to allow cross-platform builds to initialize - conventional make variables like AR and ARFLAGS. - * Added various improvements to the CI scripts in areas like version - consistency verification and text linting. - * Added version consistency verification to pngtest.c also. + * Removed the ASM implementation of ARM Neon optimizations and updated + the build accordingly. Only the remaining C implementation shall be + used from now on, thus ensuring the support of the PAC/BTI security + features on ARM64. + (Contributed by Ross Burton and John Bowler) + * Fixed the pickup of the PNG_HARDWARE_OPTIMIZATIONS option in the + CMake build on FreeBSD/amd64. This is an important performance fix + on this platform. + * Applied various fixes and improvements to the CMake build. + (Contributed by Eric Riff, Benjamin Buch and Erik Scholz) + * Added fuzzing targets for the simplified read API. + (Contributed by Mikhail Khachayants) + * Fixed a build error involving pngtest.c under a custom config. + This was a regression introduced in a code cleanup in libpng-1.6.43. + (Contributed by Ben Wagner) + * Fixed and improved the config files for AppVeyor CI and Travis CI. Send comments/corrections/commendations to png-mng-implement at lists.sf.net. diff --git a/source/libs/libpng/libpng-src/CHANGES b/source/libs/libpng/libpng-src/CHANGES index 441b57ecf..724ccca2d 100644 --- a/source/libs/libpng/libpng-src/CHANGES +++ b/source/libs/libpng/libpng-src/CHANGES @@ -6196,6 +6196,28 @@ Version 1.6.43 [February 23, 2024] consistency verification and text linting. Added version consistency verification to pngtest.c also. +Version 1.6.44 [September 12, 2024] + Hardened calculations in chroma handling to prevent overflows, and + relaxed a constraint in cHRM validation to accomodate the standard + ACES AP1 set of color primaries. + (Contributed by John Bowler) + Removed the ASM implementation of ARM Neon optimizations and updated + the build accordingly. Only the remaining C implementation shall be + used from now on, thus ensuring the support of the PAC/BTI security + features on ARM64. + (Contributed by Ross Burton and John Bowler) + Fixed the pickup of the PNG_HARDWARE_OPTIMIZATIONS option in the + CMake build on FreeBSD/amd64. This is an important performance fix + on this platform. + Applied various fixes and improvements to the CMake build. + (Contributed by Eric Riff, Benjamin Buch and Erik Scholz) + Added fuzzing targets for the simplified read API. + (Contributed by Mikhail Khachayants) + Fixed a build error involving pngtest.c under a custom config. + This was a regression introduced in a code cleanup in libpng-1.6.43. + (Contributed by Ben Wagner) + Fixed and improved the config files for AppVeyor CI and Travis CI. + Send comments/corrections/commendations to png-mng-implement at lists.sf.net. Subscription is required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement diff --git a/source/libs/libpng/libpng-src/CMakeLists.txt b/source/libs/libpng/libpng-src/CMakeLists.txt index ad3f2427d..16cc2617d 100644 --- a/source/libs/libpng/libpng-src/CMakeLists.txt +++ b/source/libs/libpng/libpng-src/CMakeLists.txt @@ -19,7 +19,7 @@ cmake_minimum_required(VERSION 3.6) set(PNGLIB_MAJOR 1) set(PNGLIB_MINOR 6) -set(PNGLIB_REVISION 43) +set(PNGLIB_REVISION 44) set(PNGLIB_SUBREVISION 0) #set(PNGLIB_SUBREVISION "git") set(PNGLIB_VERSION ${PNGLIB_MAJOR}.${PNGLIB_MINOR}.${PNGLIB_REVISION}) @@ -90,6 +90,21 @@ endif() option(PNG_DEBUG "Enable debug output" OFF) option(PNG_HARDWARE_OPTIMIZATIONS "Enable hardware optimizations" ON) +# Initialize and show the target architecture variable PNG_TARGET_ARCHITECTURE. +# +# NOTE: +# On macOS, CMake sets CMAKE_SYSTEM_PROCESSOR to either "x86_64" or "arm64", +# based upon the OS architecture, not the target architecture. As such, we need +# to check CMAKE_OSX_ARCHITECTURES to identify which hardware-specific flags to +# enable. Note that this will fail if you attempt to build a universal binary +# in a single CMake invocation. +if (APPLE AND CMAKE_OSX_ARCHITECTURES) + string(TOLOWER "${CMAKE_OSX_ARCHITECTURES}" PNG_TARGET_ARCHITECTURE) +else() + string(TOLOWER "${CMAKE_SYSTEM_PROCESSOR}" PNG_TARGET_ARCHITECTURE) +endif() +message(STATUS "Building for target architecture: ${PNG_TARGET_ARCHITECTURE}") + # Allow the users to specify a custom location of zlib. # This option is deprecated, and no longer needed with CMake 3.12 and newer. # Under the CMake policy CMP0074, if zlib is being built alongside libpng as a @@ -119,22 +134,11 @@ else() # libm is not available or not needed. endif() -# CMake currently sets CMAKE_SYSTEM_PROCESSOR to one of x86_64 or arm64 on macOS, -# based upon the OS architecture, not the target architecture. As such, we need -# to check CMAKE_OSX_ARCHITECTURES to identify which hardware-specific flags to -# enable. Note that this will fail if you attempt to build a universal binary in -# a single CMake invocation. -if (APPLE AND CMAKE_OSX_ARCHITECTURES) - set(TARGET_ARCH ${CMAKE_OSX_ARCHITECTURES}) -else() - set(TARGET_ARCH ${CMAKE_SYSTEM_PROCESSOR}) -endif() - if(PNG_HARDWARE_OPTIMIZATIONS) # Set definitions and sources for ARM. -if(TARGET_ARCH MATCHES "^(ARM|arm|aarch)") - if(TARGET_ARCH MATCHES "^(ARM64|arm64|aarch64)") +if(PNG_TARGET_ARCHITECTURE MATCHES "^(arm|aarch)") + if(PNG_TARGET_ARCHITECTURE MATCHES "^(arm64|aarch64)") set(PNG_ARM_NEON_POSSIBLE_VALUES on off) set(PNG_ARM_NEON "on" CACHE STRING "Enable ARM NEON optimizations: on|off; on is default") @@ -153,9 +157,6 @@ if(TARGET_ARCH MATCHES "^(ARM|arm|aarch)") arm/arm_init.c arm/filter_neon_intrinsics.c arm/palette_neon_intrinsics.c) - if(NOT MSVC) - list(APPEND libpng_arm_sources arm/filter_neon.S) - endif() if(PNG_ARM_NEON STREQUAL "on") add_definitions(-DPNG_ARM_NEON_OPT=2) elseif(PNG_ARM_NEON STREQUAL "check") @@ -167,7 +168,7 @@ if(TARGET_ARCH MATCHES "^(ARM|arm|aarch)") endif() # Set definitions and sources for PowerPC. -if(TARGET_ARCH MATCHES "^(powerpc|ppc64)") +if(PNG_TARGET_ARCHITECTURE MATCHES "^(powerpc|ppc64)") set(PNG_POWERPC_VSX_POSSIBLE_VALUES on off) set(PNG_POWERPC_VSX "on" CACHE STRING "Enable POWERPC VSX optimizations: on|off; on is default") @@ -189,7 +190,7 @@ if(TARGET_ARCH MATCHES "^(powerpc|ppc64)") endif() # Set definitions and sources for Intel. -if(TARGET_ARCH MATCHES "^(i[3-6]86|x86|AMD64)") +if(PNG_TARGET_ARCHITECTURE MATCHES "^(i[3-6]86|x86|amd64)") set(PNG_INTEL_SSE_POSSIBLE_VALUES on off) set(PNG_INTEL_SSE "on" CACHE STRING "Enable INTEL_SSE optimizations: on|off; on is default") @@ -211,7 +212,7 @@ if(TARGET_ARCH MATCHES "^(i[3-6]86|x86|AMD64)") endif() # Set definitions and sources for MIPS. -if(TARGET_ARCH MATCHES "^(mipsel|mips64el)") +if(PNG_TARGET_ARCHITECTURE MATCHES "^(mipsel|mips64el)") set(PNG_MIPS_MSA_POSSIBLE_VALUES on off) set(PNG_MIPS_MSA "on" CACHE STRING "Enable MIPS_MSA optimizations: on|off; on is default") @@ -258,7 +259,7 @@ if(TARGET_ARCH MATCHES "^(mipsel|mips64el)") endif() # Set definitions and sources for LoongArch. -if(TARGET_ARCH MATCHES "^(loongarch)") +if(PNG_TARGET_ARCHITECTURE MATCHES "^(loongarch)") include(CheckCCompilerFlag) set(PNG_LOONGARCH_LSX_POSSIBLE_VALUES on off) set(PNG_LOONGARCH_LSX "on" @@ -289,27 +290,27 @@ endif() else(PNG_HARDWARE_OPTIMIZATIONS) # Set definitions and sources for ARM. -if(TARGET_ARCH MATCHES "^(ARM|arm|aarch)") +if(PNG_TARGET_ARCHITECTURE MATCHES "^(arm|aarch)") add_definitions(-DPNG_ARM_NEON_OPT=0) endif() # Set definitions and sources for PowerPC. -if(TARGET_ARCH MATCHES "^(powerpc|ppc64)") +if(PNG_TARGET_ARCHITECTURE MATCHES "^(powerpc|ppc64)") add_definitions(-DPNG_POWERPC_VSX_OPT=0) endif() # Set definitions and sources for Intel. -if(TARGET_ARCH MATCHES "^(i[3-6]86|x86|AMD64)") +if(PNG_TARGET_ARCHITECTURE MATCHES "^(i[3-6]86|x86|amd64)") add_definitions(-DPNG_INTEL_SSE_OPT=0) endif() # Set definitions and sources for MIPS. -if(TARGET_ARCH MATCHES "^(mipsel|mips64el)") +if(PNG_TARGET_ARCHITECTURE MATCHES "^(mipsel|mips64el)") add_definitions(-DPNG_MIPS_MSA_OPT=0) endif() # Set definitions and sources for LoongArch. -if(TARGET_ARCH MATCHES "^(loongarch)") +if(PNG_TARGET_ARCHITECTURE MATCHES "^(loongarch)") add_definitions(-DPNG_LOONGARCH_LSX_OPT=0) endif() @@ -362,8 +363,6 @@ else() message(STATUS "Could not find an AWK-compatible program") endif() -include_directories(${CMAKE_CURRENT_BINARY_DIR}) - if(NOT AWK OR ANDROID OR IOS) # No awk available to generate sources; use pre-built pnglibconf.h configure_file(${CMAKE_CURRENT_SOURCE_DIR}/scripts/pnglibconf.h.prebuilt @@ -714,6 +713,8 @@ if(PNG_SHARED) endif() target_include_directories(png_shared PUBLIC $) + target_include_directories(png_shared + PUBLIC $) target_include_directories(png_shared SYSTEM INTERFACE $) target_link_libraries(png_shared PUBLIC ZLIB::ZLIB ${M_LIBRARY}) @@ -728,6 +729,8 @@ if(PNG_STATIC) DEBUG_POSTFIX "${PNG_DEBUG_POSTFIX}") target_include_directories(png_static PUBLIC $) + target_include_directories(png_static + PUBLIC $) target_include_directories(png_static SYSTEM INTERFACE $) target_link_libraries(png_static PUBLIC ZLIB::ZLIB ${M_LIBRARY}) @@ -757,6 +760,8 @@ if(PNG_FRAMEWORK) set_target_properties(png_framework PROPERTIES DEFINE_SYMBOL "") target_include_directories(png_framework PUBLIC $) + target_include_directories(png_framework + PUBLIC $) target_include_directories(png_framework SYSTEM INTERFACE $) target_link_libraries(png_framework PUBLIC ZLIB::ZLIB ${M_LIBRARY}) @@ -1128,6 +1133,30 @@ if(NOT SKIP_INSTALL_EXPORT AND NOT SKIP_INSTALL_ALL) FILE libpng${PNGLIB_ABI_VERSION}.cmake) endif() +# Create a CMake Config File that can be used via find_package(PNG CONFIG) +if(NOT SKIP_INSTALL_CONFIG_FILE AND NOT SKIP_INSTALL_ALL) + install(TARGETS ${PNG_LIBRARY_TARGETS} + EXPORT PNGTargets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + FRAMEWORK DESTINATION ${CMAKE_INSTALL_LIBDIR}) + + include(CMakePackageConfigHelpers) + write_basic_package_version_file(PNGConfigVersion.cmake + VERSION ${PNGLIB_VERSION} + COMPATIBILITY SameMinorVersion) + + install(EXPORT PNGTargets + FILE PNGTargets.cmake + NAMESPACE PNG:: + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/PNG) + + install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/scripts/cmake/PNGConfig.cmake + ${CMAKE_CURRENT_BINARY_DIR}/PNGConfigVersion.cmake + DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/PNG) +endif() + # TODO: Create MSVC import lib for MinGW-compiled shared lib. # pexports libpng.dll > libpng.def # lib /def:libpng.def /machine:x86 diff --git a/source/libs/libpng/libpng-src/Makefile.am b/source/libs/libpng/libpng-src/Makefile.am index 1f06c703a..eed986c2b 100644 --- a/source/libs/libpng/libpng-src/Makefile.am +++ b/source/libs/libpng/libpng-src/Makefile.am @@ -108,7 +108,7 @@ libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES = png.c pngerror.c\ if PNG_ARM_NEON libpng@PNGLIB_MAJOR@@PNGLIB_MINOR@_la_SOURCES += arm/arm_init.c\ - arm/filter_neon.S arm/filter_neon_intrinsics.c \ + arm/filter_neon_intrinsics.c \ arm/palette_neon_intrinsics.c endif diff --git a/source/libs/libpng/libpng-src/README b/source/libs/libpng/libpng-src/README index a6ca3ae9f..3af606889 100644 --- a/source/libs/libpng/libpng-src/README +++ b/source/libs/libpng/libpng-src/README @@ -1,4 +1,4 @@ -README for libpng version 1.6.43 +README for libpng version 1.6.44 ================================ See the note about version numbers near the top of `png.h`. diff --git a/source/libs/libpng/libpng-src/arm/filter_neon.S b/source/libs/libpng/libpng-src/arm/filter_neon.S index 2308aad13..fc3c7a296 100644 --- a/source/libs/libpng/libpng-src/arm/filter_neon.S +++ b/source/libs/libpng/libpng-src/arm/filter_neon.S @@ -1,253 +1,61 @@ -/* filter_neon.S - NEON optimised filter functions +/* filter_neon.S - placeholder file * - * Copyright (c) 2018 Cosmin Truta - * Copyright (c) 2014,2017 Glenn Randers-Pehrson - * Written by Mans Rullgard, 2011. + * Copyright (c) 2024 Cosmin Truta * * This code is released under the libpng license. * For conditions of distribution and use, see the disclaimer * and license in png.h */ +/* IMPORTANT NOTE: + * + * Historically, the hand-coded assembler implementation of Neon optimizations + * in this module had not been in sync with the intrinsics-based implementation + * in filter_neon_intrinsics.c and palette_neon_intrinsics.c, at least since + * the introduction of riffled palette optimizations. Moreover, the assembler + * code used to work on 32-bit ARM only, and it caused problems, even if empty, + * on 64-bit ARM. + * + * All references to this module from our internal build scripts and projects + * have been removed. + * + * For the external projects that might still expect this module to be present, + * we leave this stub in place, for the remaining lifetime of libpng-1.6.x. + * Everything should continue to function normally, as long as there are no + * deliberate attempts to use the old hand-made assembler code. A build error + * will be raised otherwise. + */ + /* This is required to get the symbol renames, which are #defines, and the * definitions (or not) of PNG_ARM_NEON_OPT and PNG_ARM_NEON_IMPLEMENTATION. */ #define PNG_VERSION_INFO_ONLY #include "../pngpriv.h" -#if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__) -.section .note.GNU-stack,"",%progbits /* mark stack as non-executable */ -#endif - #ifdef PNG_READ_SUPPORTED - -/* Assembler NEON support - only works for 32-bit ARM (i.e. it does not work for - * ARM64). The code in arm/filter_neon_intrinsics.c supports ARM64, however it - * only works if -mfpu=neon is specified on the GCC command line. See pngpriv.h - * for the logic which sets PNG_USE_ARM_NEON_ASM: - */ #if PNG_ARM_NEON_IMPLEMENTATION == 2 /* hand-coded assembler */ - #if PNG_ARM_NEON_OPT > 0 -#ifdef __ELF__ -# define ELF +#if defined(__clang__) +#define GNUC_VERSION 0 /* not gcc, although it might pretend to be */ +#elif defined(__GNUC__) +#define GNUC_MAJOR (__GNUC__ + 0) +#define GNUC_MINOR (__GNUC_MINOR__ + 0) +#define GNUC_PATCHLEVEL (__GNUC_PATCHLEVEL__ + 0) +#define GNUC_VERSION (GNUC_MAJOR * 10000 + GNUC_MINOR * 100 + GNUC_PATCHLEVEL) #else -# define ELF @ +#define GNUC_VERSION 0 /* not gcc */ #endif - .arch armv7-a - .fpu neon - -.macro func name, export=0 - .macro endfunc -ELF .size \name, . - \name - .endfunc - .purgem endfunc - .endm - .text - - /* Explicitly specifying alignment here because some versions of - * GAS don't align code correctly. This is harmless in correctly - * written versions of GAS. - */ - .align 2 - - .if \export - .global \name - .endif -ELF .type \name, STT_FUNC - .func \name -\name: -.endm - -func png_read_filter_row_sub4_neon, export=1 - ldr r3, [r0, #4] @ rowbytes - vmov.i8 d3, #0 -1: - vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] - vadd.u8 d0, d3, d4 - vadd.u8 d1, d0, d5 - vadd.u8 d2, d1, d6 - vadd.u8 d3, d2, d7 - vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! - subs r3, r3, #16 - bgt 1b - - bx lr -endfunc - -func png_read_filter_row_sub3_neon, export=1 - ldr r3, [r0, #4] @ rowbytes - vmov.i8 d3, #0 - mov r0, r1 - mov r2, #3 - mov r12, #12 - vld1.8 {q11}, [r0], r12 -1: - vext.8 d5, d22, d23, #3 - vadd.u8 d0, d3, d22 - vext.8 d6, d22, d23, #6 - vadd.u8 d1, d0, d5 - vext.8 d7, d23, d23, #1 - vld1.8 {q11}, [r0], r12 - vst1.32 {d0[0]}, [r1,:32], r2 - vadd.u8 d2, d1, d6 - vst1.32 {d1[0]}, [r1], r2 - vadd.u8 d3, d2, d7 - vst1.32 {d2[0]}, [r1], r2 - vst1.32 {d3[0]}, [r1], r2 - subs r3, r3, #12 - bgt 1b - - bx lr -endfunc - -func png_read_filter_row_up_neon, export=1 - ldr r3, [r0, #4] @ rowbytes -1: - vld1.8 {q0}, [r1,:128] - vld1.8 {q1}, [r2,:128]! - vadd.u8 q0, q0, q1 - vst1.8 {q0}, [r1,:128]! - subs r3, r3, #16 - bgt 1b - - bx lr -endfunc - -func png_read_filter_row_avg4_neon, export=1 - ldr r12, [r0, #4] @ rowbytes - vmov.i8 d3, #0 -1: - vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] - vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]! - vhadd.u8 d0, d3, d16 - vadd.u8 d0, d0, d4 - vhadd.u8 d1, d0, d17 - vadd.u8 d1, d1, d5 - vhadd.u8 d2, d1, d18 - vadd.u8 d2, d2, d6 - vhadd.u8 d3, d2, d19 - vadd.u8 d3, d3, d7 - vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! - subs r12, r12, #16 - bgt 1b - - bx lr -endfunc - -func png_read_filter_row_avg3_neon, export=1 - push {r4,lr} - ldr r12, [r0, #4] @ rowbytes - vmov.i8 d3, #0 - mov r0, r1 - mov r4, #3 - mov lr, #12 - vld1.8 {q11}, [r0], lr -1: - vld1.8 {q10}, [r2], lr - vext.8 d5, d22, d23, #3 - vhadd.u8 d0, d3, d20 - vext.8 d17, d20, d21, #3 - vadd.u8 d0, d0, d22 - vext.8 d6, d22, d23, #6 - vhadd.u8 d1, d0, d17 - vext.8 d18, d20, d21, #6 - vadd.u8 d1, d1, d5 - vext.8 d7, d23, d23, #1 - vld1.8 {q11}, [r0], lr - vst1.32 {d0[0]}, [r1,:32], r4 - vhadd.u8 d2, d1, d18 - vst1.32 {d1[0]}, [r1], r4 - vext.8 d19, d21, d21, #1 - vadd.u8 d2, d2, d6 - vhadd.u8 d3, d2, d19 - vst1.32 {d2[0]}, [r1], r4 - vadd.u8 d3, d3, d7 - vst1.32 {d3[0]}, [r1], r4 - subs r12, r12, #12 - bgt 1b - - pop {r4,pc} -endfunc - -.macro paeth rx, ra, rb, rc - vaddl.u8 q12, \ra, \rb @ a + b - vaddl.u8 q15, \rc, \rc @ 2*c - vabdl.u8 q13, \rb, \rc @ pa - vabdl.u8 q14, \ra, \rc @ pb - vabd.u16 q15, q12, q15 @ pc - vcle.u16 q12, q13, q14 @ pa <= pb - vcle.u16 q13, q13, q15 @ pa <= pc - vcle.u16 q14, q14, q15 @ pb <= pc - vand q12, q12, q13 @ pa <= pb && pa <= pc - vmovn.u16 d28, q14 - vmovn.u16 \rx, q12 - vbsl d28, \rb, \rc - vbsl \rx, \ra, d28 -.endm - -func png_read_filter_row_paeth4_neon, export=1 - ldr r12, [r0, #4] @ rowbytes - vmov.i8 d3, #0 - vmov.i8 d20, #0 -1: - vld4.32 {d4[],d5[],d6[],d7[]}, [r1,:128] - vld4.32 {d16[],d17[],d18[],d19[]},[r2,:128]! - paeth d0, d3, d16, d20 - vadd.u8 d0, d0, d4 - paeth d1, d0, d17, d16 - vadd.u8 d1, d1, d5 - paeth d2, d1, d18, d17 - vadd.u8 d2, d2, d6 - paeth d3, d2, d19, d18 - vmov d20, d19 - vadd.u8 d3, d3, d7 - vst4.32 {d0[0],d1[0],d2[0],d3[0]},[r1,:128]! - subs r12, r12, #16 - bgt 1b - - bx lr -endfunc - -func png_read_filter_row_paeth3_neon, export=1 - push {r4,lr} - ldr r12, [r0, #4] @ rowbytes - vmov.i8 d3, #0 - vmov.i8 d4, #0 - mov r0, r1 - mov r4, #3 - mov lr, #12 - vld1.8 {q11}, [r0], lr -1: - vld1.8 {q10}, [r2], lr - paeth d0, d3, d20, d4 - vext.8 d5, d22, d23, #3 - vadd.u8 d0, d0, d22 - vext.8 d17, d20, d21, #3 - paeth d1, d0, d17, d20 - vst1.32 {d0[0]}, [r1,:32], r4 - vext.8 d6, d22, d23, #6 - vadd.u8 d1, d1, d5 - vext.8 d18, d20, d21, #6 - paeth d2, d1, d18, d17 - vext.8 d7, d23, d23, #1 - vld1.8 {q11}, [r0], lr - vst1.32 {d1[0]}, [r1], r4 - vadd.u8 d2, d2, d6 - vext.8 d19, d21, d21, #1 - paeth d3, d2, d19, d18 - vst1.32 {d2[0]}, [r1], r4 - vmov d4, d19 - vadd.u8 d3, d3, d7 - vst1.32 {d3[0]}, [r1], r4 - subs r12, r12, #12 - bgt 1b +#if (GNUC_VERSION > 0) && (GNUC_VERSION < 40300) +#error "PNG_ARM_NEON is not supported with gcc versions earlier than 4.3.0" +#elif GNUC_VERSION == 40504 +#error "PNG_ARM_NEON is not supported with gcc version 4.5.4" +#else +#error "Please use 'arm/*_neon_intrinsics.c' for PNG_ARM_NEON support" +#endif - pop {r4,pc} -endfunc #endif /* PNG_ARM_NEON_OPT > 0 */ -#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 (assembler) */ +#endif /* PNG_ARM_NEON_IMPLEMENTATION == 2 */ #endif /* READ */ diff --git a/source/libs/libpng/libpng-src/ci/targets/android/ci_env.aarch64-linux-android.sh b/source/libs/libpng/libpng-src/ci/targets/android/ci_env.aarch64-linux-android.sh new file mode 100644 index 000000000..fef0ef138 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/android/ci_env.aarch64-linux-android.sh @@ -0,0 +1,16 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=aarch64 +export CI_TARGET_ARCHVER=aarch64 +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=android +export CI_TARGET_ABIVER=android29 + +export CI_CC="$CI_TARGET_ARCHVER-$CI_TARGET_SYSTEM-$CI_TARGET_ABIVER-clang" +export CI_AR="llvm-ar" +export CI_RANLIB="llvm-ranlib" diff --git a/source/libs/libpng/libpng-src/ci/targets/android/ci_env.armv7a-linux-androideabi.sh b/source/libs/libpng/libpng-src/ci/targets/android/ci_env.armv7a-linux-androideabi.sh new file mode 100644 index 000000000..c27bd121e --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/android/ci_env.armv7a-linux-androideabi.sh @@ -0,0 +1,16 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=arm +export CI_TARGET_ARCHVER=armv7a +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=androideabi +export CI_TARGET_ABIVER=androideabi29 + +export CI_CC="$CI_TARGET_ARCHVER-$CI_TARGET_SYSTEM-$CI_TARGET_ABIVER-clang" +export CI_AR="llvm-ar" +export CI_RANLIB="llvm-ranlib" diff --git a/source/libs/libpng/libpng-src/ci/targets/android/ci_env.i686-linux-android.sh b/source/libs/libpng/libpng-src/ci/targets/android/ci_env.i686-linux-android.sh new file mode 100644 index 000000000..88e369082 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/android/ci_env.i686-linux-android.sh @@ -0,0 +1,16 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=i686 +export CI_TARGET_ARCHVER=i686 +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=android +export CI_TARGET_ABIVER=android29 + +export CI_CC="$CI_TARGET_ARCHVER-$CI_TARGET_SYSTEM-$CI_TARGET_ABIVER-clang" +export CI_AR="llvm-ar" +export CI_RANLIB="llvm-ranlib" diff --git a/source/libs/libpng/libpng-src/ci/targets/android/ci_env.x86_64-linux-android.sh b/source/libs/libpng/libpng-src/ci/targets/android/ci_env.x86_64-linux-android.sh new file mode 100644 index 000000000..87460c888 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/android/ci_env.x86_64-linux-android.sh @@ -0,0 +1,16 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=x86_64 +export CI_TARGET_ARCHVER=x86_64 +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=android +export CI_TARGET_ABIVER=android29 + +export CI_CC="$CI_TARGET_ARCHVER-$CI_TARGET_SYSTEM-$CI_TARGET_ABIVER-clang" +export CI_AR="llvm-ar" +export CI_RANLIB="llvm-ranlib" diff --git a/source/libs/libpng/libpng-src/ci/targets/cygwin/ci_env.i686-pc-cygwin.sh b/source/libs/libpng/libpng-src/ci/targets/cygwin/ci_env.i686-pc-cygwin.sh new file mode 100644 index 000000000..66b99997b --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/cygwin/ci_env.i686-pc-cygwin.sh @@ -0,0 +1,18 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=i686 +export CI_TARGET_SYSTEM=cygwin + +export CI_CC="$CI_TARGET_ARCH-pc-$CI_TARGET_SYSTEM-gcc" +export CI_AR="$CI_CC-ar" +export CI_RANLIB="$CI_CC-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=CYGWIN + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/cygwin/ci_env.x86_64-pc-cygwin.sh b/source/libs/libpng/libpng-src/ci/targets/cygwin/ci_env.x86_64-pc-cygwin.sh new file mode 100644 index 000000000..78f8c25ff --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/cygwin/ci_env.x86_64-pc-cygwin.sh @@ -0,0 +1,18 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=x86_64 +export CI_TARGET_SYSTEM=cygwin + +export CI_CC="$CI_TARGET_ARCH-pc-$CI_TARGET_SYSTEM-gcc" +export CI_AR="$CI_CC-ar" +export CI_RANLIB="$CI_CC-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=CYGWIN + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/darwin/ci_env.arm64-apple-darwin.sh b/source/libs/libpng/libpng-src/ci/targets/darwin/ci_env.arm64-apple-darwin.sh new file mode 100644 index 000000000..c54d8c760 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/darwin/ci_env.arm64-apple-darwin.sh @@ -0,0 +1,15 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=arm64 +export CI_TARGET_SYSTEM=darwin + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Darwin + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH + -DCMAKE_OSX_ARCHITECTURES=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/darwin/ci_env.x86_64-apple-darwin.sh b/source/libs/libpng/libpng-src/ci/targets/darwin/ci_env.x86_64-apple-darwin.sh new file mode 100644 index 000000000..ee87711d5 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/darwin/ci_env.x86_64-apple-darwin.sh @@ -0,0 +1,15 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=x86_64 +export CI_TARGET_SYSTEM=darwin + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Darwin + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH + -DCMAKE_OSX_ARCHITECTURES=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/freebsd/ci_env.aarch64-unknown-freebsd.sh b/source/libs/libpng/libpng-src/ci/targets/freebsd/ci_env.aarch64-unknown-freebsd.sh new file mode 100644 index 000000000..42235de7d --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/freebsd/ci_env.aarch64-unknown-freebsd.sh @@ -0,0 +1,14 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=aarch64 +export CI_TARGET_SYSTEM=freebsd + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=FreeBSD + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/freebsd/ci_env.i686-unknown-freebsd.sh b/source/libs/libpng/libpng-src/ci/targets/freebsd/ci_env.i686-unknown-freebsd.sh new file mode 100644 index 000000000..3d188f8da --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/freebsd/ci_env.i686-unknown-freebsd.sh @@ -0,0 +1,14 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=i686 +export CI_TARGET_SYSTEM=freebsd + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=FreeBSD + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/freebsd/ci_env.riscv64-unknown-freebsd.sh b/source/libs/libpng/libpng-src/ci/targets/freebsd/ci_env.riscv64-unknown-freebsd.sh new file mode 100644 index 000000000..0a02cde4f --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/freebsd/ci_env.riscv64-unknown-freebsd.sh @@ -0,0 +1,14 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=riscv64 +export CI_TARGET_SYSTEM=freebsd + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=FreeBSD + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/freebsd/ci_env.x86_64-unknown-freebsd.sh b/source/libs/libpng/libpng-src/ci/targets/freebsd/ci_env.x86_64-unknown-freebsd.sh new file mode 100644 index 000000000..c77ace53b --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/freebsd/ci_env.x86_64-unknown-freebsd.sh @@ -0,0 +1,14 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=x86_64 +export CI_TARGET_SYSTEM=freebsd + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=FreeBSD + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.aarch64-linux-gnu.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.aarch64-linux-gnu.sh new file mode 100644 index 000000000..cb85bc6d8 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.aarch64-linux-gnu.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=aarch64 +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnu + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.arm-linux-gnueabi.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.arm-linux-gnueabi.sh new file mode 100644 index 000000000..45504dfcd --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.arm-linux-gnueabi.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=arm +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnueabi + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.arm-linux-gnueabihf.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.arm-linux-gnueabihf.sh new file mode 100644 index 000000000..3eb9d1892 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.arm-linux-gnueabihf.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=arm +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnueabihf + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.i686-linux-gnu.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.i686-linux-gnu.sh new file mode 100644 index 000000000..a5efd9f7f --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.i686-linux-gnu.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=i686 +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnu + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mips-linux-gnu.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mips-linux-gnu.sh new file mode 100644 index 000000000..532c93c04 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mips-linux-gnu.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=mips +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnu + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mips64-linux-gnuabi64.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mips64-linux-gnuabi64.sh new file mode 100644 index 000000000..348d2b800 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mips64-linux-gnuabi64.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=mips64 +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnuabi64 + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mips64el-linux-gnuabi64.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mips64el-linux-gnuabi64.sh new file mode 100644 index 000000000..e264913d8 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mips64el-linux-gnuabi64.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=mips64el +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnuabi64 + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsel-linux-gnu.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsel-linux-gnu.sh new file mode 100644 index 000000000..f99050f10 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsel-linux-gnu.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=mipsel +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnu + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsisa32r6-linux-gnu.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsisa32r6-linux-gnu.sh new file mode 100644 index 000000000..0a32867f6 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsisa32r6-linux-gnu.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=mipsisa32r6 +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnu + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsisa32r6el-linux-gnu.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsisa32r6el-linux-gnu.sh new file mode 100644 index 000000000..ca0600930 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsisa32r6el-linux-gnu.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=mipsisa32r6el +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnu + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsisa64r6-linux-gnuabi64.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsisa64r6-linux-gnuabi64.sh new file mode 100644 index 000000000..6c1138fe6 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsisa64r6-linux-gnuabi64.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=mipsisa64r6 +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnuabi64 + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsisa64r6el-linux-gnuabi64.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsisa64r6el-linux-gnuabi64.sh new file mode 100644 index 000000000..f64f2fcf4 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.mipsisa64r6el-linux-gnuabi64.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=mipsisa64r6el +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnuabi64 + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.powerpc-linux-gnu.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.powerpc-linux-gnu.sh new file mode 100644 index 000000000..e50d9b502 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.powerpc-linux-gnu.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=powerpc +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnu + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.powerpc64-linux-gnu.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.powerpc64-linux-gnu.sh new file mode 100644 index 000000000..15e60adf2 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.powerpc64-linux-gnu.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=powerpc64 +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnu + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.powerpc64le-linux-gnu.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.powerpc64le-linux-gnu.sh new file mode 100644 index 000000000..be0e2ca69 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.powerpc64le-linux-gnu.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=powerpc64le +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnu + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.riscv64-linux-gnu.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.riscv64-linux-gnu.sh new file mode 100644 index 000000000..d8518d97f --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.riscv64-linux-gnu.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=riscv64 +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnu + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.x86_64-linux-gnu.sh b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.x86_64-linux-gnu.sh new file mode 100644 index 000000000..3263fbff8 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/linux/ci_env.x86_64-linux-gnu.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=x86_64 +export CI_TARGET_SYSTEM=linux +export CI_TARGET_ABI=gnu + +export CI_GCC="${CI_GCC-gcc}" + +export CI_CC="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-$CI_GCC" +export CI_AR="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ar" +export CI_RANLIB="$CI_TARGET_ARCH-$CI_TARGET_SYSTEM-$CI_TARGET_ABI-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Linux + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/msdos/ci_env.i386-pc-msdoswatcom.sh b/source/libs/libpng/libpng-src/ci/targets/msdos/ci_env.i386-pc-msdoswatcom.sh new file mode 100644 index 000000000..59f3bd58f --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/msdos/ci_env.i386-pc-msdoswatcom.sh @@ -0,0 +1,18 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=i386 +export CI_TARGET_SYSTEM=msdoswatcom + +export CI_CC="wcl386" + +# Open Watcom V2 CMake build +# https://github.com/open-watcom/open-watcom-v2/discussions/716 +export CI_CMAKE_GENERATOR="Watcom WMake" +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=DOS +" diff --git a/source/libs/libpng/libpng-src/ci/targets/msdos/ci_env.i586-pc-msdosdjgpp.sh b/source/libs/libpng/libpng-src/ci/targets/msdos/ci_env.i586-pc-msdosdjgpp.sh new file mode 100644 index 000000000..63e6d0676 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/msdos/ci_env.i586-pc-msdosdjgpp.sh @@ -0,0 +1,18 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=i586 +export CI_TARGET_SYSTEM=msdosdjgpp + +export CI_CC="$CI_TARGET_ARCH-pc-$CI_TARGET_SYSTEM-gcc" +export CI_AR="$CI_CC-ar" +export CI_RANLIB="$CI_CC-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Generic + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/msdos/ci_env.i86-pc-msdoswatcom.sh b/source/libs/libpng/libpng-src/ci/targets/msdos/ci_env.i86-pc-msdoswatcom.sh new file mode 100644 index 000000000..3059f1835 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/msdos/ci_env.i86-pc-msdoswatcom.sh @@ -0,0 +1,19 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=i86 +export CI_TARGET_SYSTEM=msdoswatcom + +export CI_CC="wcl" + +# Open Watcom V2 CMake build +# https://github.com/open-watcom/open-watcom-v2/discussions/716 +export CI_CMAKE_GENERATOR="Watcom WMake" +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=DOS + -DCMAKE_SYSTEM_PROCESSOR=I86 +" diff --git a/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.aarch64-windows-llvm.sh b/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.aarch64-windows-llvm.sh new file mode 100644 index 000000000..80244172a --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.aarch64-windows-llvm.sh @@ -0,0 +1,18 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=aarch64 +export CI_TARGET_SYSTEM=windows + +export CI_CC="clang" +export CI_AR="llvm-ar" +export CI_RANLIB="llvm-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Windows + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.i686-w64-mingw32.sh b/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.i686-w64-mingw32.sh new file mode 100644 index 000000000..8c83d0f2c --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.i686-w64-mingw32.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=i686 +export CI_TARGET_SYSTEM=mingw32 + +# The output of `uname -s` on MSYS2 is understandable, and so is +# CI_TARGET_SYSTEM above, in simplified form. (See also Cygwin.) +# But aside from that, the Mingw-w64 nomenclature is rather messy. +export CI_CC="$CI_TARGET_ARCH-w64-mingw32-gcc" +export CI_AR="$CI_CC-ar" +export CI_RANLIB="$CI_CC-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Windows + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.i686-windows-llvm.sh b/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.i686-windows-llvm.sh new file mode 100644 index 000000000..3d29f6d55 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.i686-windows-llvm.sh @@ -0,0 +1,18 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=i686 +export CI_TARGET_SYSTEM=windows + +export CI_CC="clang" +export CI_AR="llvm-ar" +export CI_RANLIB="llvm-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Windows + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.x86_64-w64-mingw32.sh b/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.x86_64-w64-mingw32.sh new file mode 100644 index 000000000..67d83557b --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.x86_64-w64-mingw32.sh @@ -0,0 +1,21 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=x86_64 +export CI_TARGET_SYSTEM=mingw64 + +# The output of `uname -s` on MSYS2 is understandable, and so is +# CI_TARGET_SYSTEM above, in simplified form. (See also Cygwin.) +# But aside from that, the Mingw-w64 nomenclature is rather messy. +export CI_CC="$CI_TARGET_ARCH-w64-mingw32-gcc" +export CI_AR="$CI_CC-ar" +export CI_RANLIB="$CI_CC-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Windows + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.x86_64-windows-llvm.sh b/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.x86_64-windows-llvm.sh new file mode 100644 index 000000000..747f99b21 --- /dev/null +++ b/source/libs/libpng/libpng-src/ci/targets/windows/ci_env.x86_64-windows-llvm.sh @@ -0,0 +1,18 @@ +# Copyright (c) 2023-2024 Cosmin Truta. +# +# Use, modification and distribution are subject to the MIT License. +# Please see the accompanying file LICENSE_MIT.txt +# +# SPDX-License-Identifier: MIT + +export CI_TARGET_ARCH=x86_64 +export CI_TARGET_SYSTEM=windows + +export CI_CC="clang" +export CI_AR="llvm-ar" +export CI_RANLIB="llvm-ranlib" + +export CI_CMAKE_VARS=" + -DCMAKE_SYSTEM_NAME=Windows + -DCMAKE_SYSTEM_PROCESSOR=$CI_TARGET_ARCH +" diff --git a/source/libs/libpng/libpng-src/configure.ac b/source/libs/libpng/libpng-src/configure.ac index 505d72ff6..22113b265 100644 --- a/source/libs/libpng/libpng-src/configure.ac +++ b/source/libs/libpng/libpng-src/configure.ac @@ -25,7 +25,7 @@ AC_PREREQ([2.68]) dnl Version number stuff here: -AC_INIT([libpng],[1.6.43],[png-mng-implement@lists.sourceforge.net]) +AC_INIT([libpng],[1.6.44],[png-mng-implement@lists.sourceforge.net]) AC_CONFIG_MACRO_DIR([scripts/autoconf]) # libpng does not follow GNU file name conventions (hence 'foreign') @@ -46,17 +46,17 @@ dnl automake, so the following is not necessary (and is not defined anyway): dnl AM_PREREQ([1.11.2]) dnl stop configure from automagically running automake -PNGLIB_VERSION=1.6.43 +PNGLIB_VERSION=1.6.44 PNGLIB_MAJOR=1 PNGLIB_MINOR=6 -PNGLIB_RELEASE=43 +PNGLIB_RELEASE=44 dnl End of version number stuff AC_CONFIG_SRCDIR([pngget.c]) AC_CONFIG_HEADERS([config.h]) -# Check for basic programs. +# Check the basic programs. AC_LANG([C]) AC_PROG_CC AM_PROG_AS diff --git a/source/libs/libpng/libpng-src/contrib/oss-fuzz/Dockerfile b/source/libs/libpng/libpng-src/contrib/oss-fuzz/Dockerfile index f5bc1a985..c9bc4145e 100644 --- a/source/libs/libpng/libpng-src/contrib/oss-fuzz/Dockerfile +++ b/source/libs/libpng/libpng-src/contrib/oss-fuzz/Dockerfile @@ -1,3 +1,5 @@ +# Copyright 2024 Cosmin Truta +# Copyright 2017 Glenn Randers-Pehrson # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,11 +17,12 @@ ################################################################################ FROM gcr.io/oss-fuzz-base/base-builder -MAINTAINER glennrp@gmail.com + RUN apt-get update && \ - apt-get install -y make autoconf automake libtool + apt-get install -y make autoconf automake libtool zlib1g-dev + +RUN git clone --depth=1 https://github.com/pnggroup/libpng.git && \ + git clone --depth=1 https://github.com/madler/zlib.git && \ + cp libpng/contrib/oss-fuzz/build.sh $SRC -RUN git clone --depth 1 https://github.com/madler/zlib.git -RUN git clone --depth 1 https://github.com/glennrp/libpng.git -RUN cp libpng/contrib/oss-fuzz/build.sh $SRC -WORKDIR libpng +WORKDIR /home/libpng diff --git a/source/libs/libpng/libpng-src/contrib/oss-fuzz/README.txt b/source/libs/libpng/libpng-src/contrib/oss-fuzz/README.txt index 66d5242c5..b01af52ac 100644 --- a/source/libs/libpng/libpng-src/contrib/oss-fuzz/README.txt +++ b/source/libs/libpng/libpng-src/contrib/oss-fuzz/README.txt @@ -1,3 +1,7 @@ +libpng additions to oss-fuzz +============================ + +Copyright (c) 2024 Cosmin Truta Copyright (c) 2017 Glenn Randers-Pehrson This code is released under the libpng license. diff --git a/source/libs/libpng/libpng-src/contrib/oss-fuzz/build.sh b/source/libs/libpng/libpng-src/contrib/oss-fuzz/build.sh index 7b8f02639..1970f9c06 100755 --- a/source/libs/libpng/libpng-src/contrib/oss-fuzz/build.sh +++ b/source/libs/libpng/libpng-src/contrib/oss-fuzz/build.sh @@ -1,6 +1,8 @@ -#!/bin/bash -eu +#!/usr/bin/env bash +set -eu -# Copyright 2017-2018 Glenn Randers-Pehrson +# Copyright 2024 Cosmin Truta +# Copyright 2017 Glenn Randers-Pehrson # Copyright 2016 Google Inc. # # Licensed under the Apache License, Version 2.0 (the "License"); @@ -15,36 +17,31 @@ # See the License for the specific language governing permissions and # limitations under the License. # -# Revisions by Glenn Randers-Pehrson, 2017: -# 1. Build only the library, not the tools (changed "make -j$(nproc) all" to -# "make -j$(nproc) libpng16.la"). -# 2. Disabled WARNING and WRITE options in pnglibconf.dfa. -# 3. Build zlib alongside libpng ################################################################################ # Disable logging via library build configuration control. -cat scripts/pnglibconf.dfa | \ - sed -e "s/option STDIO/option STDIO disabled/" \ - -e "s/option WARNING /option WARNING disabled/" \ - -e "s/option WRITE enables WRITE_INT_FUNCTIONS/option WRITE disabled/" \ -> scripts/pnglibconf.dfa.temp -mv scripts/pnglibconf.dfa.temp scripts/pnglibconf.dfa +sed -e "s/option STDIO/option STDIO disabled/" \ + -e "s/option WARNING /option WARNING disabled/" \ + -e "s/option WRITE enables WRITE_INT_FUNCTIONS/option WRITE disabled/" \ + scripts/pnglibconf.dfa >scripts/pnglibconf.dfa.tmp +mv -f scripts/pnglibconf.dfa.tmp scripts/pnglibconf.dfa -# build the libpng library. +# Build the libpng library ("libpng16.la"), excluding the auxiliary tools. autoreconf -f -i ./configure --with-libpng-prefix=OSS_FUZZ_ make -j$(nproc) clean make -j$(nproc) libpng16.la -# build libpng_read_fuzzer. +# Build libpng_read_fuzzer. $CXX $CXXFLAGS -std=c++11 -I. \ $SRC/libpng/contrib/oss-fuzz/libpng_read_fuzzer.cc \ -o $OUT/libpng_read_fuzzer \ -lFuzzingEngine .libs/libpng16.a -lz -# add seed corpus. +# Add seed corpus. find $SRC/libpng -name "*.png" | grep -v crashers | \ xargs zip $OUT/libpng_read_fuzzer_seed_corpus.zip cp $SRC/libpng/contrib/oss-fuzz/*.dict \ - $SRC/libpng/contrib/oss-fuzz/*.options $OUT/ + $SRC/libpng/contrib/oss-fuzz/*.options \ + $OUT/ diff --git a/source/libs/libpng/libpng-src/contrib/oss-fuzz/libpng_read_fuzzer.cc b/source/libs/libpng/libpng-src/contrib/oss-fuzz/libpng_read_fuzzer.cc index 0190cf786..ad9f9adc6 100644 --- a/source/libs/libpng/libpng-src/contrib/oss-fuzz/libpng_read_fuzzer.cc +++ b/source/libs/libpng/libpng-src/contrib/oss-fuzz/libpng_read_fuzzer.cc @@ -204,5 +204,21 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { png_read_end(png_handler.png_ptr, png_handler.end_info_ptr); PNG_CLEANUP + +#ifdef PNG_SIMPLIFIED_READ_SUPPORTED + // Simplified READ API + png_image image; + memset(&image, 0, (sizeof image)); + image.version = PNG_IMAGE_VERSION; + + if (!png_image_begin_read_from_memory(&image, data, size)) { + return 0; + } + + image.format = PNG_FORMAT_RGBA; + std::vector buffer(PNG_IMAGE_SIZE(image)); + png_image_finish_read(&image, NULL, buffer.data(), 0, NULL); +#endif + return 0; } diff --git a/source/libs/libpng/libpng-src/contrib/tools/chkfmt.sh b/source/libs/libpng/libpng-src/contrib/tools/chkfmt.sh deleted file mode 100644 index 8810aa7b5..000000000 --- a/source/libs/libpng/libpng-src/contrib/tools/chkfmt.sh +++ /dev/null @@ -1,157 +0,0 @@ -#!/bin/sh - -# chkfmt.sh -# -# COPYRIGHT: -# Written by John Cunningham Bowler, 2010. -# Revised by Cosmin Truta, 2022. -# To the extent possible under law, the author has waived all copyright and -# related or neighboring rights to this work. The author published this work -# from the United States. -# -# Check the format of the source files in the current directory: -# -# * The lines should not exceed a predefined maximum length. -# * Tab characters should appear only where necessary (e.g. in makefiles). -# -# Optionally arguments are files or directories to check. -# -# -v: output the long lines (makes fixing them easier) -# -e: spawn an editor for each file that needs a change ($EDITOR must be -# defined). When using -e the script MUST be run from an interactive -# command line. - -script_name=`basename "$0"` - -verbose= -edit= -vers= -test "$1" = "-v" && { - shift - verbose=yes -} -test "$1" = "-e" && { - shift - if test -n "$EDITOR" - then - edit=yes - - # Copy the standard streams for the editor - exec 3>&0 4>&1 5>&2 - else - echo "$script_name -e: EDITOR must be defined" >&2 - exit 1 - fi -} - -# Function to edit a single file - if the file isn't changed ask the user -# whether or not to continue. This stuff only works if the script is run -# from the command line (otherwise, don't specify -e or you will be sorry). -doed(){ - cp "$file" "$file".orig - "$EDITOR" "$file" 0>&3 1>&4 2>&5 3>&- 4>&- 5>&- || exit 1 - if cmp -s "$file".orig "$file" - then - rm "$file".orig - echo -n "$file: file not changed, type anything to continue: " >&5 - read ans 0>&3 - test -n "$ans" || return 1 - fi - return 0 -} - -# In beta versions, the version string which appears in files can be a little -# long and cause spuriously overlong lines. To avoid this, substitute the -# version string with a placeholder string "a.b.cc" before checking for long -# lines. -# (Starting from libpng version 1.6.36, we switched to a conventional Git -# workflow, and we are no longer publishing beta versions.) -if test -r png.h -then - vers="`sed -n -e \ - 's/^#define PNG_LIBPNG_VER_STRING .\([0-9]\.[0-9]\.[0-9][0-9a-z]*\).$/\1/p' \ - png.h`" - echo "$script_name: checking version $vers" -fi -if test -z "$vers" -then - echo "$script_name: png.h not found, ignoring version number" >&2 -fi - -test -n "$1" || set -- . -find "$@" \( -type d \( -name '.git' -o -name '.libs' -o -name 'projects' \) \ - -prune \) -o \( -type f \ - ! -name '*.[oa]' ! -name '*.l[oa]' ! -name '*.png' ! -name '*.out' \ - ! -name '*.jpg' ! -name '*.patch' ! -name '*.obj' ! -name '*.exe' \ - ! -name '*.com' ! -name '*.tar.*' ! -name '*.zip' ! -name '*.ico' \ - ! -name '*.res' ! -name '*.rc' ! -name '*.mms' ! -name '*.rej' \ - ! -name '*.dsp' ! -name '*.orig' ! -name '*.dfn' ! -name '*.swp' \ - ! -name '~*' ! -name '*.3' \ - ! -name 'missing' ! -name 'mkinstalldirs' ! -name 'depcomp' \ - ! -name 'aclocal.m4' ! -name 'install-sh' ! -name 'Makefile.in' \ - ! -name 'ltmain.sh' ! -name 'config*' -print \) | { - st=0 - while read file - do - case "$file" in - *.mak|*[Mm]akefile.*|*[Mm]akefile) - # Makefiles require tabs, dependency lines can be this long. - check_tabs= - line_length=100;; - *.awk) - # Allow literal tabs. - check_tabs= - # Mainframe line printer, anyone? - line_length=132;; - */ci_*.sh) - check_tabs=yes - line_length=100;; - *contrib/*/*.[ch]) - check_tabs=yes - line_length=100;; - *) - check_tabs=yes - line_length=80;; - esac - - # Note that vers can only contain 0-9, . and a-z - if test -n "$vers" - then - sed -e "s/$vers/a.b.cc/g" "$file" >"$file".$$ - else - cp "$file" "$file".$$ - fi - splt="`fold -$line_length "$file".$$ | diff -c "$file".$$ -`" - rm "$file".$$ - - if test -n "$splt" - then - echo "$file: lines too long" - st=1 - if test -n "$EDITOR" -a -n "$edit" - then - doed "$file" || exit 1 - elif test -n "$verbose" - then - echo "$splt" - fi - fi - if test -n "$check_tabs" - then - tab="`tr -c -d '\t' <"$file"`" - if test -n "$tab" - then - echo "$file: file contains tab characters" - st=1 - if test -n "$EDITOR" -a -n "$edit" - then - doed "$file" || exit 1 - elif test -n "$verbose" - then - echo "$splt" - fi - fi - fi - done - exit $st -} diff --git a/source/libs/libpng/libpng-src/libpng-manual.txt b/source/libs/libpng/libpng-src/libpng-manual.txt index 798805759..2ce366d67 100644 --- a/source/libs/libpng/libpng-src/libpng-manual.txt +++ b/source/libs/libpng/libpng-src/libpng-manual.txt @@ -9,7 +9,7 @@ libpng-manual.txt - A description on how to use and modify libpng Based on: - libpng version 1.6.36, December 2018, through 1.6.43 - February 2024 + libpng version 1.6.36, December 2018, through 1.6.44 - September 2024 Updated and distributed by Cosmin Truta Copyright (c) 2018-2024 Cosmin Truta diff --git a/source/libs/libpng/libpng-src/libpng.3 b/source/libs/libpng/libpng-src/libpng.3 index 45e76e483..5a3c89cb9 100644 --- a/source/libs/libpng/libpng-src/libpng.3 +++ b/source/libs/libpng/libpng-src/libpng.3 @@ -1,6 +1,6 @@ -.TH LIBPNG 3 "February 23, 2024" +.TH LIBPNG 3 "September 12, 2024" .SH NAME -libpng \- Portable Network Graphics (PNG) Reference Library 1.6.43 +libpng \- Portable Network Graphics (PNG) Reference Library 1.6.44 .SH SYNOPSIS \fB#include \fP @@ -528,7 +528,7 @@ libpng-manual.txt - A description on how to use and modify libpng Based on: - libpng version 1.6.36, December 2018, through 1.6.43 - February 2024 + libpng version 1.6.36, December 2018, through 1.6.44 - September 2024 Updated and distributed by Cosmin Truta Copyright (c) 2018-2024 Cosmin Truta diff --git a/source/libs/libpng/libpng-src/libpngpf.3 b/source/libs/libpng/libpng-src/libpngpf.3 index 0abec74a2..b7557ca27 100644 --- a/source/libs/libpng/libpng-src/libpngpf.3 +++ b/source/libs/libpng/libpng-src/libpngpf.3 @@ -1,6 +1,6 @@ -.TH LIBPNGPF 3 "February 23, 2024" +.TH LIBPNGPF 3 "September 12, 2024" .SH NAME -libpng \- Portable Network Graphics (PNG) Reference Library 1.6.43 +libpng \- Portable Network Graphics (PNG) Reference Library 1.6.44 (private functions) .SH SYNOPSIS diff --git a/source/libs/libpng/libpng-src/png.5 b/source/libs/libpng/libpng-src/png.5 index a8a681813..14a3c432b 100644 --- a/source/libs/libpng/libpng-src/png.5 +++ b/source/libs/libpng/libpng-src/png.5 @@ -1,4 +1,4 @@ -.TH PNG 5 "February 23, 2024" +.TH PNG 5 "September 12, 2024" .SH NAME png \- Portable Network Graphics (PNG) format diff --git a/source/libs/libpng/libpng-src/png.c b/source/libs/libpng/libpng-src/png.c index 9ed315700..9a9fb23d9 100644 --- a/source/libs/libpng/libpng-src/png.c +++ b/source/libs/libpng/libpng-src/png.c @@ -14,7 +14,7 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_43 Your_png_h_is_not_version_1_6_43; +typedef png_libpng_version_1_6_44 Your_png_h_is_not_version_1_6_44; /* Tells libpng that we have already handled the first "num_bytes" bytes * of the PNG file signature. If the PNG data is embedded into another @@ -794,7 +794,7 @@ png_get_copyright(png_const_structrp png_ptr) return PNG_STRING_COPYRIGHT #else return PNG_STRING_NEWLINE \ - "libpng version 1.6.43" PNG_STRING_NEWLINE \ + "libpng version 1.6.44" PNG_STRING_NEWLINE \ "Copyright (c) 2018-2024 Cosmin Truta" PNG_STRING_NEWLINE \ "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \ PNG_STRING_NEWLINE \ @@ -1203,6 +1203,24 @@ png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr) #endif /* GAMMA */ #ifdef PNG_COLORSPACE_SUPPORTED +static int +png_safe_add(png_int_32 *addend0_and_result, png_int_32 addend1, + png_int_32 addend2) { + /* Safely add three integers. Returns 0 on success, 1 on overlow. + * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore + * relying on addition of two positive values producing a negative one is not + * safe. + */ + int addend0 = *addend0_and_result; + if (0x7fffffff - addend0 < addend1) + return 1; + addend0 += addend1; + if (0x7fffffff - addend1 < addend2) + return 1; + *addend0_and_result = addend0 + addend2; + return 0; +} + /* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for * cHRM, as opposed to using chromaticities. These internal APIs return * non-zero on a parameter error. The X, Y and Z values are required to be @@ -1211,38 +1229,52 @@ png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr) static int png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ) { - png_int_32 d, dwhite, whiteX, whiteY; + png_int_32 d, dred, dgreen, dwhite, whiteX, whiteY; - d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z; + /* 'd' in each of the blocks below is just X+Y+Z for each component, + * x, y and z are X,Y,Z/(X+Y+Z). + */ + d = XYZ->red_X; + if (png_safe_add(&d, XYZ->red_Y, XYZ->red_Z)) + return 1; if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0) return 1; if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0) return 1; - dwhite = d; + dred = d; whiteX = XYZ->red_X; whiteY = XYZ->red_Y; - d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z; + d = XYZ->green_X; + if (png_safe_add(&d, XYZ->green_Y, XYZ->green_Z)) + return 1; if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0) return 1; if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0) return 1; - dwhite += d; + dgreen = d; whiteX += XYZ->green_X; whiteY += XYZ->green_Y; - d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z; + d = XYZ->blue_X; + if (png_safe_add(&d, XYZ->blue_Y, XYZ->blue_Z)) + return 1; if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0) return 1; if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0) return 1; - dwhite += d; whiteX += XYZ->blue_X; whiteY += XYZ->blue_Y; - /* The reference white is simply the sum of the end-point (X,Y,Z) vectors, - * thus: + /* The reference white is simply the sum of the end-point (X,Y,Z) vectors so + * the fillowing calculates (X+Y+Z) of the reference white (media white, + * encoding white) itself: */ + if (png_safe_add(&d, dred, dgreen)) + return 1; + + dwhite = d; + if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0) return 1; if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0) @@ -1257,20 +1289,6 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) png_fixed_point red_inverse, green_inverse, blue_scale; png_fixed_point left, right, denominator; - /* Check xy and, implicitly, z. Note that wide gamut color spaces typically - * have end points with 0 tristimulus values (these are impossible end - * points, but they are used to cover the possible colors). We check - * xy->whitey against 5, not 0, to avoid a possible integer overflow. - */ - if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1; - if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1; - if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1; - if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1; - if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1; - if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1; - if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1; - if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1; - /* The reverse calculation is more difficult because the original tristimulus * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8 * derived values were recorded in the cHRM chunk; @@ -1451,16 +1469,16 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) * value of 2 indicates an internal error to the caller. */ if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0) - return 2; + return 1; if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0) - return 2; + return 1; denominator = left - right; /* Now find the red numerator. */ if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0) - return 2; + return 1; if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0) - return 2; + return 1; /* Overflow is possible here and it indicates an extreme set of PNG cHRM * chunk values. This calculation actually returns the reciprocal of the @@ -1473,9 +1491,9 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) /* Similarly for green_inverse: */ if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0) - return 2; + return 1; if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0) - return 2; + return 1; if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 || green_inverse <= xy->whitey) return 1; @@ -1520,25 +1538,14 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) static int png_XYZ_normalize(png_XYZ *XYZ) { - png_int_32 Y; + png_int_32 Y, Ytemp; - if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 || - XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 || - XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0) + /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1. */ + Ytemp = XYZ->red_Y; + if (png_safe_add(&Ytemp, XYZ->green_Y, XYZ->blue_Y)) return 1; - /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1. - * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore - * relying on addition of two positive values producing a negative one is not - * safe. - */ - Y = XYZ->red_Y; - if (0x7fffffff - Y < XYZ->green_X) - return 1; - Y += XYZ->green_Y; - if (0x7fffffff - Y < XYZ->blue_X) - return 1; - Y += XYZ->blue_Y; + Y = Ytemp; if (Y != PNG_FP_1) { diff --git a/source/libs/libpng/libpng-src/png.h b/source/libs/libpng/libpng-src/png.h index 83d390312..04a233f39 100644 --- a/source/libs/libpng/libpng-src/png.h +++ b/source/libs/libpng/libpng-src/png.h @@ -1,7 +1,7 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.43 + * libpng version 1.6.44 * * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson @@ -15,7 +15,7 @@ * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger * libpng versions 0.97, January 1998, through 1.6.35, July 2018: * Glenn Randers-Pehrson - * libpng versions 1.6.36, December 2018, through 1.6.43, February 2024: + * libpng versions 1.6.36, December 2018, through 1.6.44, September 2024: * Cosmin Truta * See also "Contributing Authors", below. */ @@ -239,7 +239,7 @@ * ... * 1.5.30 15 10530 15.so.15.30[.0] * ... - * 1.6.43 16 10643 16.so.16.43[.0] + * 1.6.44 16 10644 16.so.16.44[.0] * * Henceforth the source version will match the shared-library major and * minor numbers; the shared-library major version number will be used for @@ -275,7 +275,7 @@ */ /* Version information for png.h - this should match the version in png.c */ -#define PNG_LIBPNG_VER_STRING "1.6.43" +#define PNG_LIBPNG_VER_STRING "1.6.44" #define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n" /* The versions of shared library builds should stay in sync, going forward */ @@ -286,18 +286,18 @@ /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */ #define PNG_LIBPNG_VER_MAJOR 1 #define PNG_LIBPNG_VER_MINOR 6 -#define PNG_LIBPNG_VER_RELEASE 43 +#define PNG_LIBPNG_VER_RELEASE 44 /* This should be zero for a public release, or non-zero for a * development version. */ -#define PNG_LIBPNG_VER_BUILD 0 +#define PNG_LIBPNG_VER_BUILD 0 /* Release Status */ -#define PNG_LIBPNG_BUILD_ALPHA 1 -#define PNG_LIBPNG_BUILD_BETA 2 -#define PNG_LIBPNG_BUILD_RC 3 -#define PNG_LIBPNG_BUILD_STABLE 4 +#define PNG_LIBPNG_BUILD_ALPHA 1 +#define PNG_LIBPNG_BUILD_BETA 2 +#define PNG_LIBPNG_BUILD_RC 3 +#define PNG_LIBPNG_BUILD_STABLE 4 #define PNG_LIBPNG_BUILD_RELEASE_STATUS_MASK 7 /* Release-Specific Flags */ @@ -317,7 +317,7 @@ * From version 1.0.1 it is: * XXYYZZ, where XX=major, YY=minor, ZZ=release */ -#define PNG_LIBPNG_VER 10643 /* 1.6.43 */ +#define PNG_LIBPNG_VER 10644 /* 1.6.44 */ /* Library configuration: these options cannot be changed after * the library has been built. @@ -427,7 +427,7 @@ extern "C" { /* This triggers a compiler error in png.c, if png.c and png.h * do not agree upon the version number. */ -typedef char* png_libpng_version_1_6_43; +typedef char* png_libpng_version_1_6_44; /* Basic control structions. Read libpng-manual.txt or libpng.3 for more info. * @@ -824,7 +824,7 @@ typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp, * your compiler. This may be very difficult - try using a different compiler * to build the library! */ -PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); +PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), (jmp_buf, int), typedef); #endif /* Transform masks for the high-level interface */ diff --git a/source/libs/libpng/libpng-src/pngconf.h b/source/libs/libpng/libpng-src/pngconf.h index 000d7b1a8..4a4b58ac8 100644 --- a/source/libs/libpng/libpng-src/pngconf.h +++ b/source/libs/libpng/libpng-src/pngconf.h @@ -1,7 +1,7 @@ /* pngconf.h - machine-configurable file for libpng * - * libpng version 1.6.43 + * libpng version 1.6.44 * * Copyright (c) 2018-2024 Cosmin Truta * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson @@ -88,7 +88,7 @@ /* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect * against legacy (pre ISOC90) compilers that did not understand function - * prototypes. It is not required for modern C compilers. + * prototypes. [Deprecated.] */ #ifndef PNGARG # define PNGARG(arglist) arglist @@ -298,7 +298,7 @@ #ifndef PNG_EXPORTA # define PNG_EXPORTA(ordinal, type, name, args, attributes) \ - PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \ + PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), args, \ PNG_LINKAGE_API attributes) #endif @@ -316,7 +316,7 @@ #endif #ifndef PNG_CALLBACK -# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) PNGARG(args) +# define PNG_CALLBACK(type, name, args) type (PNGCBAPI name) args #endif /* Support for compiler specific function attributes. These are used diff --git a/source/libs/libpng/libpng-src/pngerror.c b/source/libs/libpng/libpng-src/pngerror.c index 29ebda794..1babf9f8d 100644 --- a/source/libs/libpng/libpng-src/pngerror.c +++ b/source/libs/libpng/libpng-src/pngerror.c @@ -20,13 +20,14 @@ #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) -static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr, - png_const_charp error_message)),PNG_NORETURN); +static PNG_FUNCTION(void /* PRIVATE */, +png_default_error,(png_const_structrp png_ptr, png_const_charp error_message), + PNG_NORETURN); #ifdef PNG_WARNINGS_SUPPORTED static void /* PRIVATE */ -png_default_warning PNGARG((png_const_structrp png_ptr, - png_const_charp warning_message)); +png_default_warning(png_const_structrp png_ptr, + png_const_charp warning_message); #endif /* WARNINGS */ /* This function is called whenever there is a fatal error. This function diff --git a/source/libs/libpng/libpng-src/pnglibconf.h b/source/libs/libpng/libpng-src/pnglibconf.h index 83f09fbe7..f5ce441ec 100644 --- a/source/libs/libpng/libpng-src/pnglibconf.h +++ b/source/libs/libpng/libpng-src/pnglibconf.h @@ -1,6 +1,6 @@ /* pnglibconf.h - library build configuration */ -/* libpng version 1.6.43 */ +/* libpng version 1.6.44 */ /* Copyright (c) 2018-2024 Cosmin Truta */ /* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ diff --git a/source/libs/libpng/libpng-src/pngpriv.h b/source/libs/libpng/libpng-src/pngpriv.h index 9bfdb7134..b59084e7e 100644 --- a/source/libs/libpng/libpng-src/pngpriv.h +++ b/source/libs/libpng/libpng-src/pngpriv.h @@ -140,47 +140,6 @@ * callbacks to do this. */ # define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon - - /* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used - * if possible - if __ARM_NEON__ is set and the compiler version is not known - * to be broken. This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can - * be: - * - * 1 The intrinsics code (the default with __ARM_NEON__) - * 2 The hand coded assembler (the default without __ARM_NEON__) - * - * It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however - * this is *NOT* supported and may cease to work even after a minor revision - * to libpng. It *is* valid to do this for testing purposes, e.g. speed - * testing or a new compiler, but the results should be communicated to the - * libpng implementation list for incorporation in the next minor release. - */ -# ifndef PNG_ARM_NEON_IMPLEMENTATION -# if defined(__ARM_NEON__) || defined(__ARM_NEON) -# if defined(__clang__) - /* At present it is unknown by the libpng developers which versions - * of clang support the intrinsics, however some or perhaps all - * versions do not work with the assembler so this may be - * irrelevant, so just use the default (do nothing here.) - */ -# elif defined(__GNUC__) - /* GCC 4.5.4 NEON support is known to be broken. 4.6.3 is known to - * work, so if this *is* GCC, or G++, look for a version >4.5 - */ -# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6) -# define PNG_ARM_NEON_IMPLEMENTATION 2 -# endif /* no GNUC support */ -# endif /* __GNUC__ */ -# else /* !defined __ARM_NEON__ */ - /* The 'intrinsics' code simply won't compile without this -mfpu=neon: - */ -# if !defined(__aarch64__) && !defined(_M_ARM64) - /* The assembler code currently does not work on ARM64 */ -# define PNG_ARM_NEON_IMPLEMENTATION 2 -# endif /* __aarch64__ */ -# endif /* __ARM_NEON__ */ -# endif /* !PNG_ARM_NEON_IMPLEMENTATION */ - # ifndef PNG_ARM_NEON_IMPLEMENTATION /* Use the intrinsics code by default. */ # define PNG_ARM_NEON_IMPLEMENTATION 1 diff --git a/source/libs/libpng/libpng-src/pngtest.c b/source/libs/libpng/libpng-src/pngtest.c index 45ef66a70..5969f5031 100644 --- a/source/libs/libpng/libpng-src/pngtest.c +++ b/source/libs/libpng/libpng-src/pngtest.c @@ -45,8 +45,13 @@ #include "png.h" +/* This hack was introduced for historical reasons, and we are + * still keeping it in libpng-1.6.x for compatibility reasons. + */ +#define STDERR stdout + /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_43 Your_png_h_is_not_version_1_6_43; +typedef png_libpng_version_1_6_44 Your_png_h_is_not_version_1_6_44; /* Ensure that all version numbers in png.h are consistent with one another. */ #if (PNG_LIBPNG_VER != PNG_LIBPNG_VER_MAJOR * 10000 + \ @@ -103,11 +108,6 @@ typedef png_libpng_version_1_6_43 Your_png_h_is_not_version_1_6_43; typedef FILE * png_FILE_p; #endif -/* This hack was introduced for historical reasons, and we are - * still keeping it in libpng-1.6.x for compatibility reasons. - */ -#define STDERR stdout - #ifndef PNG_DEBUG # define PNG_DEBUG 0 #endif @@ -518,9 +518,9 @@ static int maximum_allocation = 0; static int total_allocation = 0; static int num_allocations = 0; -png_voidp PNGCBAPI png_debug_malloc PNGARG((png_structp png_ptr, - png_alloc_size_t size)); -void PNGCBAPI png_debug_free PNGARG((png_structp png_ptr, png_voidp ptr)); +png_voidp PNGCBAPI png_debug_malloc(png_structp png_ptr, + png_alloc_size_t size); +void PNGCBAPI png_debug_free(png_structp png_ptr, png_voidp ptr); png_voidp PNGCBAPI png_debug_malloc(png_structp png_ptr, png_alloc_size_t size) diff --git a/source/libs/libpng/libpng-src/scripts/cmake/AUTHORS.md b/source/libs/libpng/libpng-src/scripts/cmake/AUTHORS.md index 641dde265..c09821786 100644 --- a/source/libs/libpng/libpng-src/scripts/cmake/AUTHORS.md +++ b/source/libs/libpng/libpng-src/scripts/cmake/AUTHORS.md @@ -20,6 +20,8 @@ Author List * Cosmin Truta * Dan Rosser * David Callu + * Eric Riff + * Erik Scholz * Gianfranco Costamagna * Gleb Mazovetskiy * Glenn Randers-Pehrson diff --git a/source/libs/libpng/libpng-src/scripts/cmake/PNGConfig.cmake b/source/libs/libpng/libpng-src/scripts/cmake/PNGConfig.cmake new file mode 100644 index 000000000..3b6f646de --- /dev/null +++ b/source/libs/libpng/libpng-src/scripts/cmake/PNGConfig.cmake @@ -0,0 +1,15 @@ +include(CMakeFindDependencyMacro) + +find_dependency(ZLIB REQUIRED) + +include("${CMAKE_CURRENT_LIST_DIR}/PNGTargets.cmake") + +if(NOT TARGET PNG::PNG) + if(TARGET PNG::png_shared) + add_library(PNG::PNG INTERFACE IMPORTED) + target_link_libraries(PNG::PNG INTERFACE PNG::png_shared) + elseif(TARGET PNG::png_static) + add_library(PNG::PNG INTERFACE IMPORTED) + target_link_libraries(PNG::PNG INTERFACE PNG::png_static) + endif() +endif() diff --git a/source/libs/libpng/libpng-src/scripts/cmake/README.md b/source/libs/libpng/libpng-src/scripts/cmake/README.md index ca418893a..18e710717 100644 --- a/source/libs/libpng/libpng-src/scripts/cmake/README.md +++ b/source/libs/libpng/libpng-src/scripts/cmake/README.md @@ -20,6 +20,7 @@ File List CMakeLists.txt ==> The main CMake lists file scripts/cmake/AUTHORS.md ==> The Authors file scripts/cmake/README.md ==> This file + scripts/cmake/PNGConfig.cmake ==> Config file for FindPNG scripts/cmake/genchk.cmake.in ==> Template for genchk.cmake scripts/cmake/genout.cmake.in ==> Template for genout.cmake scripts/cmake/gensrc.cmake.in ==> Template for gensrc.cmake diff --git a/source/libs/libpng/libpng-src/scripts/cmake/genout.cmake.in b/source/libs/libpng/libpng-src/scripts/cmake/genout.cmake.in index ab8285968..d4a333282 100644 --- a/source/libs/libpng/libpng-src/scripts/cmake/genout.cmake.in +++ b/source/libs/libpng/libpng-src/scripts/cmake/genout.cmake.in @@ -19,6 +19,7 @@ set(BINDIR "@CMAKE_CURRENT_BINARY_DIR@") set(AWK "@AWK@") set(CMAKE_C_COMPILER "@CMAKE_C_COMPILER@") set(CMAKE_C_FLAGS @CMAKE_C_FLAGS@) +set(CMAKE_SYSROOT @CMAKE_SYSROOT@) set(INCDIR "@CMAKE_CURRENT_BINARY_DIR@") set(PNG_PREFIX "@PNG_PREFIX@") set(PNGLIB_MAJOR "@PNGLIB_MAJOR@") @@ -38,6 +39,10 @@ if(APPLE) endif() endif() +if(CMAKE_SYSROOT) + set(PLATFORM_C_FLAGS ${PLATFORM_C_FLAGS} "--sysroot=${CMAKE_SYSROOT}") +endif() + get_filename_component(INPUTEXT "${INPUT}" EXT) get_filename_component(OUTPUTEXT "${OUTPUT}" EXT) get_filename_component(INPUTBASE "${INPUT}" NAME_WE) diff --git a/source/libs/libpng/libpng-src/scripts/dfn.awk b/source/libs/libpng/libpng-src/scripts/dfn.awk index 0b25c8a37..0b970e006 100644 --- a/source/libs/libpng/libpng-src/scripts/dfn.awk +++ b/source/libs/libpng/libpng-src/scripts/dfn.awk @@ -75,12 +75,12 @@ $1 ~ /^PNG_DFN_END_SORT/{ if (lineno == "") lineno=NR if (sub(/^[^"]*PNG_DFN *"/,"",line) != 1) { - print "line", lineno ": processing failed:" - print orig - err=1 - next + print "line", lineno ": processing failed:" + print orig + err=1 + next } else { - ++out_count + ++out_count } # Now examine quotes within the value: @@ -94,7 +94,7 @@ $1 ~ /^PNG_DFN_END_SORT/{ # #define first_name John # #define last_name Smith # - # PNG_DFN"#define name @'@" first_name "@ @" last_name "@@'" + # PNG_DFN"#define name @'@" first_name "@ @" last_name "@@'" # # Might get C preprocessed to: # @@ -102,7 +102,7 @@ $1 ~ /^PNG_DFN_END_SORT/{ # # Which this script reduces to: # - # #define name "John Smith" + # #define name "John Smith" # while (1) { # While there is an @" remove it and the next "@ @@ -195,7 +195,7 @@ $1 ~ /^PNG_DFN_END_SORT/{ END{ if (out_count > 0 || err > 0) - exit err + exit err print "no definition lines found" exit 1 diff --git a/source/libs/libpng/libpng-src/scripts/libpng-config-head.in b/source/libs/libpng/libpng-src/scripts/libpng-config-head.in index 37577f413..3d26a0a6a 100644 --- a/source/libs/libpng/libpng-src/scripts/libpng-config-head.in +++ b/source/libs/libpng/libpng-src/scripts/libpng-config-head.in @@ -11,7 +11,7 @@ # Modeled after libxml-config. -version=1.6.43 +version=1.6.44 prefix="" libdir="" libs="" diff --git a/source/libs/libpng/libpng-src/scripts/libpng.pc.in b/source/libs/libpng/libpng-src/scripts/libpng.pc.in index 6a581d1a4..fc3f6f67f 100644 --- a/source/libs/libpng/libpng-src/scripts/libpng.pc.in +++ b/source/libs/libpng/libpng-src/scripts/libpng.pc.in @@ -5,6 +5,6 @@ includedir=@includedir@/libpng16 Name: libpng Description: Loads and saves PNG files -Version: 1.6.43 +Version: 1.6.44 Libs: -L${libdir} -lpng16 Cflags: -I${includedir} diff --git a/source/libs/libpng/libpng-src/scripts/pnglibconf.h.prebuilt b/source/libs/libpng/libpng-src/scripts/pnglibconf.h.prebuilt index 83f09fbe7..f5ce441ec 100644 --- a/source/libs/libpng/libpng-src/scripts/pnglibconf.h.prebuilt +++ b/source/libs/libpng/libpng-src/scripts/pnglibconf.h.prebuilt @@ -1,6 +1,6 @@ /* pnglibconf.h - library build configuration */ -/* libpng version 1.6.43 */ +/* libpng version 1.6.44 */ /* Copyright (c) 2018-2024 Cosmin Truta */ /* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */ diff --git a/source/libs/libpng/version.ac b/source/libs/libpng/version.ac index 8f85bd0ed..da9dd431e 100644 --- a/source/libs/libpng/version.ac +++ b/source/libs/libpng/version.ac @@ -8,4 +8,4 @@ dnl dnl -------------------------------------------------------- dnl dnl m4-include this file to define the current libpng version -m4_define([libpng_version], [1.6.43]) +m4_define([libpng_version], [1.6.44]) diff --git a/source/texk/README b/source/texk/README index 662776344..660768409 100644 --- a/source/texk/README +++ b/source/texk/README @@ -106,7 +106,7 @@ ttf2pk2 - maintained here, by us ttfdump - maintained here, by us, since Taiwan upstream apparently gone. -upmendex 1.07 - by Takuji Tanaka +upmendex 1.09 - by Takuji Tanaka https://ctan.org/pkg/upmendex https://github.com/t-tk/upmendex-package diff --git a/source/texk/web2c/ChangeLog b/source/texk/web2c/ChangeLog index ab0d68881..2bb3ad137 100644 --- a/source/texk/web2c/ChangeLog +++ b/source/texk/web2c/ChangeLog @@ -1,3 +1,44 @@ +2024-09-16 TANAKA Takuji + + * tests/ec-lmr10.tfm: Add for tests of pTeX family + +2024-09-07 Karl Berry + + * Makefile.am (texprof.am): include. + * ac/web2c.ac (kpse_tex_progs) : new entry in table. + +2024-09-06 Andreas Scherer + + * weav-twill.ch, + * weave.ch: Sort section names in TWILL. + +2024-09-02 Andreas Scherer + + * bibtex.ch, + * dvitype.ch, + * gftodvi.ch, + * gftopk.ch, + * gftype.ch, + * mft.ch, + * pktype.ch, + * pltotf.ch, + * pooltype.ch, + * tangle.ch, + * tftopl.ch, + * vftovp.ch, + * vptovf.ch, + * weave.ch: Flip two section names in the index. + * dvicopy.ch, + * dvicopy.web, + * patgen.ch, + * patgen.web, + * pktogf.ch, + * pktogf.web: Fix sorting order in 'other' WEB codees. + +2024-08-31 Andreas Scherer + + * vftovp.ch: Fix sorting order of new named sections. + 2024-08-23 Andreas Scherer * gftopk.ch, diff --git a/source/texk/web2c/Makefile.am b/source/texk/web2c/Makefile.am index 6e271293a..183082f7e 100644 --- a/source/texk/web2c/Makefile.am +++ b/source/texk/web2c/Makefile.am @@ -299,6 +299,9 @@ include $(srcdir)/luatexdir/am/luatex.am ## luahbTeX include $(srcdir)/luatexdir/am/luaharfbuzz.am +## texprof +include $(srcdir)/texprofdir/am/texprof.am + ## XeTeX include $(srcdir)/xetexdir/am/xetex.am diff --git a/source/texk/web2c/Makefile.in b/source/texk/web2c/Makefile.in index 9a762efee..4900db066 100644 --- a/source/texk/web2c/Makefile.in +++ b/source/texk/web2c/Makefile.in @@ -115,22 +115,22 @@ bin_PROGRAMS = tangle$(EXEEXT) ctangle$(EXEEXT) $(am__EXEEXT_4) \ $(am__EXEEXT_20) $(am__EXEEXT_21) $(am__EXEEXT_22) \ $(am__EXEEXT_23) $(am__EXEEXT_24) $(am__EXEEXT_25) \ $(am__EXEEXT_26) $(am__EXEEXT_27) $(am__EXEEXT_28) \ - $(am__EXEEXT_29) $(am__EXEEXT_30) + $(am__EXEEXT_29) $(am__EXEEXT_30) $(am__EXEEXT_31) noinst_PROGRAMS = tangleboot$(EXEEXT) ctangleboot$(EXEEXT) \ - $(am__EXEEXT_31) $(am__EXEEXT_32) $(am__EXEEXT_33) \ - $(am__EXEEXT_34) $(am__EXEEXT_35) $(am__EXEEXT_36) \ - $(am__EXEEXT_37) $(am__EXEEXT_38) $(am__EXEEXT_39) \ - $(am__EXEEXT_40) $(am__EXEEXT_41) -TESTS = tangle.test $(am__EXEEXT_44) ctiedir/ctie.test \ + $(am__EXEEXT_32) $(am__EXEEXT_33) $(am__EXEEXT_34) \ + $(am__EXEEXT_35) $(am__EXEEXT_36) $(am__EXEEXT_37) \ + $(am__EXEEXT_38) $(am__EXEEXT_39) $(am__EXEEXT_40) \ + $(am__EXEEXT_41) $(am__EXEEXT_42) +TESTS = tangle.test $(am__EXEEXT_45) ctiedir/ctie.test \ cwebdir/ctwill.test cwebdir/cweave.test tiedir/tie.test \ $(am__append_6) $(am__append_16) $(am__append_25) \ $(am__append_34) $(am__append_42) $(am__append_55) \ $(am__append_56) $(am__append_58) $(am__append_62) \ - $(am__EXEEXT_45) $(am__append_68) $(am__append_71) \ + $(am__EXEEXT_46) $(am__append_68) $(am__append_71) \ $(am__append_76) $(am__append_81) $(am__append_84) \ $(am__append_105) $(am__append_106) $(am__append_107) \ - $(am__append_108) $(am__append_116) $(am__append_118) \ - $(am__append_120) $(am__append_143) libmd5/md5.test + $(am__append_108) $(am__append_117) $(am__append_119) \ + $(am__append_121) $(am__append_144) libmd5/md5.test @WEB_TRUE@am__append_1 = $(web_programs) @WEB_TRUE@am__append_2 = $(web_tests) @TEX_TRUE@am__append_3 = tex @@ -249,85 +249,86 @@ TESTS = tangle.test $(am__EXEEXT_44) ctiedir/ctie.test \ @LUAHBTEX_TRUE@am__append_106 = $(luahbtex_tests) @LUAJITTEX_TRUE@am__append_107 = $(luajittex_tests) @LUAJITHBTEX_TRUE@am__append_108 = $(luajithbtex_tests) -@XETEX_TRUE@am__append_109 = xetex -@XETEX_MACOSX_TRUE@am__append_110 = -DXETEX_MAC -@XETEX_MACOSX_TRUE@am__append_111 = -std=c++11 -@XETEX_MACOSX_FALSE@am__append_112 = $(FONTCONFIG_INCLUDES) -@XETEX_MACOSX_FALSE@am__append_113 = $(FONTCONFIG_LIBS) -@XETEX_MACOSX_TRUE@am__append_114 = \ +@TEXPROF_TRUE@am__append_109 = texprof texprofile +@XETEX_TRUE@am__append_110 = xetex +@XETEX_MACOSX_TRUE@am__append_111 = -DXETEX_MAC +@XETEX_MACOSX_TRUE@am__append_112 = -std=c++11 +@XETEX_MACOSX_FALSE@am__append_113 = $(FONTCONFIG_INCLUDES) +@XETEX_MACOSX_FALSE@am__append_114 = $(FONTCONFIG_LIBS) +@XETEX_MACOSX_TRUE@am__append_115 = \ @XETEX_MACOSX_TRUE@ xetexdir/XeTeXFontInst_Mac.cpp \ @XETEX_MACOSX_TRUE@ xetexdir/XeTeXFontInst_Mac.h \ @XETEX_MACOSX_TRUE@ xetexdir/XeTeXFontMgr_Mac.mm \ @XETEX_MACOSX_TRUE@ xetexdir/XeTeXFontMgr_Mac.h \ @XETEX_MACOSX_TRUE@ xetexdir/XeTeX_mac.c -@XETEX_MACOSX_FALSE@am__append_115 = \ +@XETEX_MACOSX_FALSE@am__append_116 = \ @XETEX_MACOSX_FALSE@ xetexdir/XeTeXFontMgr_FC.cpp \ @XETEX_MACOSX_FALSE@ xetexdir/XeTeXFontMgr_FC.h -@XETEX_TRUE@am__append_116 = $(xetex_tests) -@OTANGLE_TRUE@am__append_117 = $(omegaware_programs) -@OTANGLE_TRUE@am__append_118 = $(OTANGLE_tests) $(OMFONTS_tests) -@ALEPH_TRUE@am__append_119 = aleph -@ALEPH_TRUE@am__append_120 = $(aleph_tests) -@SYNCTEX_TRUE@am__append_121 = synctex -@SYNCTEX_TRUE@am__append_122 = $(LTLIBSYNCTEX) -@SYNCTEX_TRUE@am__append_123 = $(LIBSYNCTEX) -@MINGW32_TRUE@am__append_124 = $(KPATHSEA_INCLUDES) -@MINGW32_TRUE@am__append_125 = -lshlwapi $(KPATHSEA_LIBS) -@MINGW32_TRUE@am__append_126 = -lshlwapi -@TEX_SYNCTEX_TRUE@am__append_127 = -I$(srcdir)/synctexdir \ +@XETEX_TRUE@am__append_117 = $(xetex_tests) +@OTANGLE_TRUE@am__append_118 = $(omegaware_programs) +@OTANGLE_TRUE@am__append_119 = $(OTANGLE_tests) $(OMFONTS_tests) +@ALEPH_TRUE@am__append_120 = aleph +@ALEPH_TRUE@am__append_121 = $(aleph_tests) +@SYNCTEX_TRUE@am__append_122 = synctex +@SYNCTEX_TRUE@am__append_123 = $(LTLIBSYNCTEX) +@SYNCTEX_TRUE@am__append_124 = $(LIBSYNCTEX) +@MINGW32_TRUE@am__append_125 = $(KPATHSEA_INCLUDES) +@MINGW32_TRUE@am__append_126 = -lshlwapi $(KPATHSEA_LIBS) +@MINGW32_TRUE@am__append_127 = -lshlwapi +@TEX_SYNCTEX_TRUE@am__append_128 = -I$(srcdir)/synctexdir \ @TEX_SYNCTEX_TRUE@ $(ZLIB_INCLUDES) -D__SyncTeX__ \ @TEX_SYNCTEX_TRUE@ -DSYNCTEX_ENGINE_H=\"synctex-tex.h\" -@TEX_SYNCTEX_TRUE@am__append_128 = $(ZLIB_LIBS) -@TEX_SYNCTEX_TRUE@am__append_129 = $(ZLIB_DEPEND) -@TEX_SYNCTEX_TRUE@am__append_130 = \ +@TEX_SYNCTEX_TRUE@am__append_129 = $(ZLIB_LIBS) +@TEX_SYNCTEX_TRUE@am__append_130 = $(ZLIB_DEPEND) +@TEX_SYNCTEX_TRUE@am__append_131 = \ @TEX_SYNCTEX_TRUE@ synctexdir/synctex.c \ @TEX_SYNCTEX_TRUE@ synctexdir/synctex.h \ @TEX_SYNCTEX_TRUE@ synctexdir/synctex-common.h \ @TEX_SYNCTEX_TRUE@ synctexdir/synctex-tex.h -@ETEX_SYNCTEX_TRUE@am__append_131 = -I$(srcdir)/synctexdir \ +@ETEX_SYNCTEX_TRUE@am__append_132 = -I$(srcdir)/synctexdir \ @ETEX_SYNCTEX_TRUE@ $(ZLIB_INCLUDES) -D__SyncTeX__ \ @ETEX_SYNCTEX_TRUE@ -DSYNCTEX_ENGINE_H=\"synctex-etex.h\" -@ETEX_SYNCTEX_TRUE@am__append_132 = $(ZLIB_LIBS) -@ETEX_SYNCTEX_TRUE@am__append_133 = $(ZLIB_DEPEND) -@ETEX_SYNCTEX_TRUE@am__append_134 = \ +@ETEX_SYNCTEX_TRUE@am__append_133 = $(ZLIB_LIBS) +@ETEX_SYNCTEX_TRUE@am__append_134 = $(ZLIB_DEPEND) +@ETEX_SYNCTEX_TRUE@am__append_135 = \ @ETEX_SYNCTEX_TRUE@ synctexdir/synctex.c \ @ETEX_SYNCTEX_TRUE@ synctexdir/synctex.h \ @ETEX_SYNCTEX_TRUE@ synctexdir/synctex-common.h \ @ETEX_SYNCTEX_TRUE@ synctexdir/synctex-etex.h -@EUPTEX_SYNCTEX_TRUE@am__append_135 = -I$(srcdir)/synctexdir \ +@EUPTEX_SYNCTEX_TRUE@am__append_136 = -I$(srcdir)/synctexdir \ @EUPTEX_SYNCTEX_TRUE@ $(ZLIB_INCLUDES) -D__SyncTeX__ \ @EUPTEX_SYNCTEX_TRUE@ -DSYNCTEX_ENGINE_H=\"synctex-euptex.h\" -@EUPTEX_SYNCTEX_TRUE@am__append_136 = $(ZLIB_LIBS) -@EUPTEX_SYNCTEX_TRUE@am__append_137 = $(ZLIB_DEPEND) -@EUPTEX_SYNCTEX_TRUE@am__append_138 = \ +@EUPTEX_SYNCTEX_TRUE@am__append_137 = $(ZLIB_LIBS) +@EUPTEX_SYNCTEX_TRUE@am__append_138 = $(ZLIB_DEPEND) +@EUPTEX_SYNCTEX_TRUE@am__append_139 = \ @EUPTEX_SYNCTEX_TRUE@ synctexdir/synctex.c \ @EUPTEX_SYNCTEX_TRUE@ synctexdir/synctex.h \ @EUPTEX_SYNCTEX_TRUE@ synctexdir/synctex-common.h \ @EUPTEX_SYNCTEX_TRUE@ synctexdir/synctex-euptex.h -@PDFTEX_SYNCTEX_TRUE@am__append_139 = -I$(srcdir)/synctexdir \ +@PDFTEX_SYNCTEX_TRUE@am__append_140 = -I$(srcdir)/synctexdir \ @PDFTEX_SYNCTEX_TRUE@ -D__SyncTeX__ \ @PDFTEX_SYNCTEX_TRUE@ -DSYNCTEX_ENGINE_H=\"synctex-pdftex.h\" -@PDFTEX_SYNCTEX_TRUE@am__append_140 = \ +@PDFTEX_SYNCTEX_TRUE@am__append_141 = \ @PDFTEX_SYNCTEX_TRUE@ synctexdir/synctex.c \ @PDFTEX_SYNCTEX_TRUE@ synctexdir/synctex.h \ @PDFTEX_SYNCTEX_TRUE@ synctexdir/synctex-common.h \ @PDFTEX_SYNCTEX_TRUE@ synctexdir/synctex-pdftex.h -@XETEX_SYNCTEX_TRUE@am__append_141 = -I$(srcdir)/synctexdir \ +@XETEX_SYNCTEX_TRUE@am__append_142 = -I$(srcdir)/synctexdir \ @XETEX_SYNCTEX_TRUE@ -D__SyncTeX__ \ @XETEX_SYNCTEX_TRUE@ -DSYNCTEX_ENGINE_H=\"synctex-xetex.h\" -@XETEX_SYNCTEX_TRUE@am__append_142 = \ +@XETEX_SYNCTEX_TRUE@am__append_143 = \ @XETEX_SYNCTEX_TRUE@ synctexdir/synctex.c \ @XETEX_SYNCTEX_TRUE@ synctexdir/synctex.h \ @XETEX_SYNCTEX_TRUE@ synctexdir/synctex-common.h \ @XETEX_SYNCTEX_TRUE@ synctexdir/synctex-xetex.h -@SYNCTEX_TRUE@am__append_143 = $(synctex_tests) +@SYNCTEX_TRUE@am__append_144 = $(synctex_tests) subdir = . ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/m4/web2c-disable.m4 \ @@ -424,25 +425,26 @@ am__EXEEXT_3 = odvicopy$(EXEEXT) odvitype$(EXEEXT) otangle$(EXEEXT) \ @LUAHBTEX_TRUE@am__EXEEXT_24 = luahbtex$(EXEEXT) @LUAJITTEX_TRUE@am__EXEEXT_25 = luajittex$(EXEEXT) @LUAJITHBTEX_TRUE@am__EXEEXT_26 = luajithbtex$(EXEEXT) -@XETEX_TRUE@am__EXEEXT_27 = xetex$(EXEEXT) -@OTANGLE_TRUE@am__EXEEXT_28 = $(am__EXEEXT_3) -@ALEPH_TRUE@am__EXEEXT_29 = aleph$(EXEEXT) -@SYNCTEX_TRUE@am__EXEEXT_30 = synctex$(EXEEXT) +@TEXPROF_TRUE@am__EXEEXT_27 = texprof$(EXEEXT) texprofile$(EXEEXT) +@XETEX_TRUE@am__EXEEXT_28 = xetex$(EXEEXT) +@OTANGLE_TRUE@am__EXEEXT_29 = $(am__EXEEXT_3) +@ALEPH_TRUE@am__EXEEXT_30 = aleph$(EXEEXT) +@SYNCTEX_TRUE@am__EXEEXT_31 = synctex$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(libdir)" \ "$(DESTDIR)$(libdir)" "$(DESTDIR)$(bindir)" \ "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(man5dir)" \ "$(DESTDIR)$(pkgconfigdir)" "$(DESTDIR)$(syncincludedir)" -@MF_TRUE@@WIN32_TRUE@am__EXEEXT_31 = call_mf$(EXEEXT) -@MFLUA_TRUE@@WIN32_TRUE@am__EXEEXT_32 = call_mflua$(EXEEXT) -@MFLUAJIT_TRUE@@WIN32_TRUE@am__EXEEXT_33 = call_mfluajit$(EXEEXT) -@MP_TRUE@@WIN32_TRUE@am__EXEEXT_34 = call_mpost$(EXEEXT) -@PMP_TRUE@@WIN32_TRUE@am__EXEEXT_35 = call_pmpost$(EXEEXT) -@UPMP_TRUE@@WIN32_TRUE@am__EXEEXT_36 = call_upmpost$(EXEEXT) -@HITEX_TRUE@am__EXEEXT_37 = himktables$(EXEEXT) -@LUATEX_TRUE@@WIN32_TRUE@am__EXEEXT_38 = call_luatex$(EXEEXT) -@LUAHBTEX_TRUE@@WIN32_TRUE@am__EXEEXT_39 = call_luahbtex$(EXEEXT) -@LUAJITTEX_TRUE@@WIN32_TRUE@am__EXEEXT_40 = call_luajittex$(EXEEXT) -@LUAJITHBTEX_TRUE@@WIN32_TRUE@am__EXEEXT_41 = \ +@MF_TRUE@@WIN32_TRUE@am__EXEEXT_32 = call_mf$(EXEEXT) +@MFLUA_TRUE@@WIN32_TRUE@am__EXEEXT_33 = call_mflua$(EXEEXT) +@MFLUAJIT_TRUE@@WIN32_TRUE@am__EXEEXT_34 = call_mfluajit$(EXEEXT) +@MP_TRUE@@WIN32_TRUE@am__EXEEXT_35 = call_mpost$(EXEEXT) +@PMP_TRUE@@WIN32_TRUE@am__EXEEXT_36 = call_pmpost$(EXEEXT) +@UPMP_TRUE@@WIN32_TRUE@am__EXEEXT_37 = call_upmpost$(EXEEXT) +@HITEX_TRUE@am__EXEEXT_38 = himktables$(EXEEXT) +@LUATEX_TRUE@@WIN32_TRUE@am__EXEEXT_39 = call_luatex$(EXEEXT) +@LUAHBTEX_TRUE@@WIN32_TRUE@am__EXEEXT_40 = call_luahbtex$(EXEEXT) +@LUAJITTEX_TRUE@@WIN32_TRUE@am__EXEEXT_41 = call_luajittex$(EXEEXT) +@LUAJITHBTEX_TRUE@@WIN32_TRUE@am__EXEEXT_42 = \ @LUAJITHBTEX_TRUE@@WIN32_TRUE@ call_luajithbtex$(EXEEXT) PROGRAMS = $(bin_PROGRAMS) $(noinst_PROGRAMS) am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; @@ -1599,6 +1601,10 @@ tex_OBJECTS = $(dist_tex_OBJECTS) $(nodist_tex_OBJECTS) @TEX_SYNCTEX_TRUE@am__DEPENDENCIES_13 = $(am__DEPENDENCIES_1) tex_DEPENDENCIES = $(am__DEPENDENCIES_2) $(am__DEPENDENCIES_1) \ $(am__DEPENDENCIES_13) +texprof_SOURCES = texprof.c +texprof_OBJECTS = texprof-texprof.$(OBJEXT) +texprofile_SOURCES = texprofile.c +texprofile_OBJECTS = texprofile-texprofile.$(OBJEXT) nodist_tftopl_OBJECTS = tftopl.$(OBJEXT) tftopl_OBJECTS = $(nodist_tftopl_OBJECTS) tftopl_LDADD = $(LDADD) @@ -1803,7 +1809,8 @@ am__depfiles_remade = ./$(DEPDIR)/aleph-aleph-pool.Po \ ./$(DEPDIR)/ptex-ptexini.Po ./$(DEPDIR)/tangle.Po \ ./$(DEPDIR)/tangleboot.Po ./$(DEPDIR)/tex-tex-pool.Po \ ./$(DEPDIR)/tex-tex0.Po ./$(DEPDIR)/tex-texextra.Po \ - ./$(DEPDIR)/tex-texini.Po ./$(DEPDIR)/tftopl.Po \ + ./$(DEPDIR)/tex-texini.Po ./$(DEPDIR)/texprof-texprof.Po \ + ./$(DEPDIR)/texprofile-texprofile.Po ./$(DEPDIR)/tftopl.Po \ ./$(DEPDIR)/tie-tie.Po ./$(DEPDIR)/twill.Po \ ./$(DEPDIR)/upbibtex-upbibtex.Po \ ./$(DEPDIR)/updvitype-updvitype.Po ./$(DEPDIR)/upmpost-pmp.Po \ @@ -2516,8 +2523,8 @@ SOURCES = $(libff_a_SOURCES) $(libkanji_a_SOURCES) \ $(nodist_pmpost_SOURCES) $(nodist_pooltype_SOURCES) \ $(dist_ptex_SOURCES) $(nodist_ptex_SOURCES) $(synctex_SOURCES) \ $(nodist_tangle_SOURCES) $(nodist_tangleboot_SOURCES) \ - $(dist_tex_SOURCES) $(nodist_tex_SOURCES) \ - $(nodist_tftopl_SOURCES) $(nodist_tie_SOURCES) \ + $(dist_tex_SOURCES) $(nodist_tex_SOURCES) texprof.c \ + texprofile.c $(nodist_tftopl_SOURCES) $(nodist_tie_SOURCES) \ $(ttf2afm_SOURCES) $(EXTRA_ttf2afm_SOURCES) \ $(nodist_twill_SOURCES) $(upbibtex_SOURCES) \ $(nodist_upbibtex_SOURCES) $(updvitype_SOURCES) \ @@ -2546,10 +2553,11 @@ DIST_SOURCES = $(libff_a_SOURCES) $(libkanji_a_SOURCES) \ $(dist_mf_nowin_SOURCES) $(dist_mflua_SOURCES) \ $(dist_mfluajit_SOURCES) $(am__dist_pdftex_SOURCES_DIST) \ $(pdftosrc_SOURCES) $(dist_ptex_SOURCES) $(synctex_SOURCES) \ - $(am__dist_tex_SOURCES_DIST) $(ttf2afm_SOURCES) \ - $(EXTRA_ttf2afm_SOURCES) $(upbibtex_SOURCES) \ - $(updvitype_SOURCES) $(uppltotf_SOURCES) $(dist_uptex_SOURCES) \ - $(uptftopl_SOURCES) $(am__dist_xetex_SOURCES_DIST) + $(am__dist_tex_SOURCES_DIST) texprof.c texprofile.c \ + $(ttf2afm_SOURCES) $(EXTRA_ttf2afm_SOURCES) \ + $(upbibtex_SOURCES) $(updvitype_SOURCES) $(uppltotf_SOURCES) \ + $(dist_uptex_SOURCES) $(uptftopl_SOURCES) \ + $(am__dist_xetex_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive cscopelist-recursive \ ctags-recursive dvi-recursive html-recursive info-recursive \ install-data-recursive install-dvi-recursive \ @@ -2761,15 +2769,15 @@ am__set_TESTS_bases = \ bases=`echo $$bases` AM_TESTSUITE_SUMMARY_HEADER = ' for $(PACKAGE_STRING)' RECHECK_LOGS = $(TEST_LOGS) -am__EXEEXT_42 = bibtex.test dvicopy.test dvitype.test gftodvi.test \ +am__EXEEXT_43 = bibtex.test dvicopy.test dvitype.test gftodvi.test \ gftopk.test gftype.test mft.test patgen.test pktogf.test \ pktype.test pltotf.test pooltype.test tftopl.test vftovp.test \ vptovf.test weave.test twill.test -am__EXEEXT_43 = $(am__EXEEXT_42) tests/bibtex-openout-test.pl \ +am__EXEEXT_44 = $(am__EXEEXT_43) tests/bibtex-openout-test.pl \ tests/bibtex-longline-test.pl tests/bibtex-mem.test \ tests/bibtex-bigauth.test tests/bibtex-auxinclude.test -@WEB_TRUE@am__EXEEXT_44 = $(am__EXEEXT_43) -am__EXEEXT_45 = +@WEB_TRUE@am__EXEEXT_45 = $(am__EXEEXT_44) +am__EXEEXT_46 = TEST_SUITE_LOG = test-suite.log am__test_logs1 = $(TESTS:=.log) am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log) @@ -2822,8 +2830,9 @@ am__DIST_COMMON = $(dist_man_MANS) $(srcdir)/../../am/bin_links.am \ $(srcdir)/pdftexdir/am/ttf2afm.am \ $(srcdir)/pmpostdir/am/pmpost.am $(srcdir)/ptexdir/am/ptex.am \ $(srcdir)/silent-sh.in $(srcdir)/synctexdir/am/synctex.am \ - $(srcdir)/tangle-sh.in $(srcdir)/uptexdir/am/uptex.am \ - $(srcdir)/web2c-sh.in $(srcdir)/xetexdir/am/xetex.am \ + $(srcdir)/tangle-sh.in $(srcdir)/texprofdir/am/texprof.am \ + $(srcdir)/uptexdir/am/uptex.am $(srcdir)/web2c-sh.in \ + $(srcdir)/xetexdir/am/xetex.am \ $(top_srcdir)/../../build-aux/ar-lib \ $(top_srcdir)/../../build-aux/compile \ $(top_srcdir)/../../build-aux/config.guess \ @@ -3002,7 +3011,7 @@ NM = @NM@ NMEDIT = @NMEDIT@ OBJCXX = @OBJCXX@ OBJCXXDEPMODE = @OBJCXXDEPMODE@ -OBJCXXFLAGS = @OBJCXXFLAGS@ $(am__append_111) +OBJCXXFLAGS = @OBJCXXFLAGS@ $(am__append_112) OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTANGLE = @OTANGLE@ @@ -3151,8 +3160,8 @@ EXTRA_LIBRARIES = libmf.a libmflua.a libmfluaotfcc.a libmfluapotrace.a \ libluaharfbuzz.a libluajitharfbuzz.a libxetex.a libsynctex.a \ libmd5.a EXTRA_LTLIBRARIES = libsynctex.la -lib_LIBRARIES = $(am__append_123) -lib_LTLIBRARIES = $(am__append_122) +lib_LIBRARIES = $(am__append_124) +lib_LTLIBRARIES = $(am__append_123) dist_man_MANS = synctexdir/man1/synctex.1 synctexdir/man5/synctex.5 nodist_man_MANS = TEST_EXTENSIONS = .pl .test @@ -3261,6 +3270,14 @@ EXTRA_DIST = PROJECTS cftests cpascal.h help.h w2c/config.h \ ptexdir/tests/chcode-euc.pl ptexdir/tests/chcode-sjis.pl \ ptexdir/tests/skipjfmp.pl ptexdir/tests/skipjfmp.tfm \ ptexdir/ptrip/ptrip.diffs ptexdir/ptrip/texmf.cnf \ + ptexdir/tests/ctrlsym.tex ptexdir/tests/ctrlsym.log \ + ptexdir/tests/endlinechar.tex ptexdir/tests/endline.log \ + ptexdir/tests/control-symbol.tex ptexdir/tests/jctrlsym.log \ + ptexdir/tests/p-endlinea.typ ptexdir/tests/p-jctrlsyma.typ \ + ptexdir/tests/printkanji.tex ptexdir/tests/pknj-s.log \ + ptexdir/tests/pknj-e.log ptexdir/tests/p-pknj-sa.typ \ + ptexdir/tests/p-pknj-ea.typ ptexdir/tests/ucs.tex \ + ptexdir/tests/ucs-s.log ptexdir/tests/ucs-e.log \ $(uptex_web_srcs) $(uptex_ch_srcs) uptexdir/uptex.defines \ uptexdir/upbibtex.ch uptexdir/updvitype.ch \ uptexdir/uppltotf.ch uptexdir/uptftopl.ch uptexdir/COPYRIGHT \ @@ -3484,9 +3501,10 @@ EXTRA_DIST = PROJECTS cftests cpascal.h help.h w2c/config.h \ luatexdir/luaharfbuzz/luaharfbuzz-scm-1.rockspec \ luatexdir/luaharfbuzz/Makefile luatexdir/luaharfbuzz/README.md \ luatexdir/luaharfbuzz/README-win.md \ - luatexdir/luaharfbuzz/THANKS $(xetex_web_srcs) \ - $(xetex_ch_srcs) xetexdir/xetex.defines xetexdir/ChangeLog \ - xetexdir/COPYING xetexdir/NEWS xetexdir/image/README \ + luatexdir/luaharfbuzz/THANKS texprofdir/ChangeLog \ + $(texprof_web) $(xetex_web_srcs) $(xetex_ch_srcs) \ + xetexdir/xetex.defines xetexdir/ChangeLog xetexdir/COPYING \ + xetexdir/NEWS xetexdir/image/README \ xetexdir/unicode-char-prep.pl xetexdir/xewebmac.tex \ $(xetex_tests) xetexdir/tests/bug73.log \ xetexdir/tests/bug73.tex xetexdir/tests/filedump.log \ @@ -3599,21 +3617,22 @@ DISTCLEANFILES = CXXLD.sh tangle.c tangle.h tangle.p tangle-web2c \ ptests/memtest.bib ptests/memtest?.* ptests/xstory.dvityp \ ptests/xpagenum.typ ptests/xptex[34]*.typ ptests/xcmr10.tfm \ ptests/xcmr10.pl ptests/xsample*.typ ptests/x*min10.* \ - ptests/xchcode*.* ptests/xskipjfmp.* ptrip.diffs \ - $(nodist_uptex_SOURCES) uptex.web uptex.ch uptex-web2c uptex.p \ - uptex.pool uptex-tangle $(upweb_programs:=.c) \ - $(upweb_programs:=.h) $(upweb_programs:=.p) \ - $(upweb_programs:=-web2c) $(upweb_programs:=.web) \ - uptests/nissya_bib.* uptests/xexampl.aux uptests/xexampl.bbl \ - uptests/xexampl.blg uptests/xenc*.* uptests/fn*.* \ - uptests/memtest.bib uptests/memtest?.* uptests/xstory.dvityp \ - uptests/xpagenum.typ uptests/x*ptex[345]*.typ \ - uptests/xcmr10.tfm uptests/xcmr10.pl uptests/xsample*.typ \ - uptests/x*min10.* uptests/xchcode*.* uptests/xtestnewu*.* \ - uptests/xuparse.* uptests/yuparse.* uptests/ygkhuge*.* \ - uptests/ygk256*.* uptests/xskipjfmp.* uptrip.diffs \ - $(nodist_euptex_SOURCES) euptex.web euptex.ch euptex-web2c \ - euptex.p euptex.pool euptex-tangle euptrip.diffs \ + ptests/xchcode*.* ptests/xskipjfmp.* ptrip.diffs p-ctrlsym.log \ + p-ctrlsym.out p-ctrlsym.tex p-endline*.* p-jctrlsym*.* \ + p-pknj-*.* p-ucs*.* $(nodist_uptex_SOURCES) uptex.web uptex.ch \ + uptex-web2c uptex.p uptex.pool uptex-tangle \ + $(upweb_programs:=.c) $(upweb_programs:=.h) \ + $(upweb_programs:=.p) $(upweb_programs:=-web2c) \ + $(upweb_programs:=.web) uptests/nissya_bib.* \ + uptests/xexampl.aux uptests/xexampl.bbl uptests/xexampl.blg \ + uptests/xenc*.* uptests/fn*.* uptests/memtest.bib \ + uptests/memtest?.* uptests/xstory.dvityp uptests/xpagenum.typ \ + uptests/x*ptex[345]*.typ uptests/xcmr10.tfm uptests/xcmr10.pl \ + uptests/xsample*.typ uptests/x*min10.* uptests/xchcode*.* \ + uptests/xtestnewu*.* uptests/xuparse.* uptests/yuparse.* \ + uptests/ygkhuge*.* uptests/ygk256*.* uptests/xskipjfmp.* \ + uptrip.diffs $(nodist_euptex_SOURCES) euptex.web euptex.ch \ + euptex-web2c euptex.p euptex.pool euptex-tangle euptrip.diffs \ pdfprimitive-euptex.* eup-ctrlsym.fmt eup-ctrlsym.log \ eup-ctrlsym.out eup-ctrlsym.tex $(nodist_hitex_SOURCES) \ $(nodist_hishrink_SOURCES) $(nodist_histretch_SOURCES) \ @@ -3624,6 +3643,7 @@ DISTCLEANFILES = CXXLD.sh tangle.c tangle.h tangle.p tangle-web2c \ partoken-ok.log partoken-xfail.log pdftests/fn*.* postV3.afm \ postV7.afm test-13.pdf test-13.xref test-15.pdf test-15.xref \ $(nodist_libluatex_sources) luaimage.* luajitimage.* \ + $(nodist_texprof_SOURCES) texprofile-tangle texprof-tangle \ $(nodist_xetex_SOURCES) xetex.web xetex-final.ch xetex-web2c \ xetex.p xetex.pool xetex-tangle bug73.fmt bug73.log bug73.out \ bug73.tex filedump.log filedump.out filedump.tex \ @@ -3846,18 +3866,18 @@ tie_CPPFLAGS = $(AM_CPPFLAGS) -DNOT_WEB2C initex_CPPFLAGS = -DEXEPROG=\"tex.exe\" nodist_initex_SOURCES = callexe.c initex_LDADD = -tex_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_127) +tex_CPPFLAGS = $(AM_CPPFLAGS) $(am__append_128) # With --enable-ipc, TeX may need to link with -lsocket. -tex_LDADD = $(LDADD) $(ipc_socketlibs) $(am__append_128) +tex_LDADD = $(LDADD) $(ipc_socketlibs) $(am__append_129) # TeX C sources tex_c_h = texini.c tex0.c texcoerce.h texd.h nodist_tex_SOURCES = $(tex_c_h) tex-pool.c -dist_tex_SOURCES = texextra.c $(am__append_130) +dist_tex_SOURCES = texextra.c $(am__append_131) # We must create texd.h before building the tex_OBJECTS. -tex_prereq = texd.h $(am__append_129) +tex_prereq = texd.h $(am__append_130) tex_ch_srcs = \ tex.web \ tex.ch \ @@ -4357,21 +4377,21 @@ libmplib_web = mplibdir/mp.w mplibdir/psout.w mplibdir/svgout.w \ mplibdir/pngout.w mplibdir/mpmath.w mplibdir/mpmathbinary.w \ mplibdir/mpmathinterval.w mplibdir/mpmathdecimal.w \ mplibdir/mpmathdouble.w mplibdir/mpstrings.w mplibdir/tfmin.w -etex_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_INCLUDES) $(am__append_131) +etex_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_INCLUDES) $(am__append_132) # With --enable-ipc, e-TeX may need to link with -lsocket. -etex_LDADD = $(LDADD) $(ZLIB_LIBS) $(ipc_socketlibs) $(am__append_132) +etex_LDADD = $(LDADD) $(ZLIB_LIBS) $(ipc_socketlibs) $(am__append_133) etex_DEPENDENCIES = $(ZLIB_DEPEND) # e-TeX C sources etex_c_h = etexini.c etex0.c etexcoerce.h etexd.h nodist_etex_SOURCES = $(etex_c_h) etex-pool.c dist_etex_SOURCES = etexdir/etexextra.c etexdir/etexextra.h \ - etexdir/etex_version.h $(am__append_134) + etexdir/etex_version.h $(am__append_135) # We must create etexd.h and etexdir/etex_version.h before building the # etex_OBJECTS. -etex_prereq = etexd.h etexdir/etex_version.h $(am__append_133) +etex_prereq = etexd.h etexdir/etex_version.h $(am__append_134) etex_web_srcs = \ tex.web \ etexdir/etex.ch @@ -4436,7 +4456,10 @@ ptex_ch_srcs = \ ptex_tests = \ ptexdir/ptriptest.test \ ptexdir/pver.test \ - ptexdir/wcfname.test + ptexdir/wcfname.test \ + ptexdir/ptex-ctrlsym.test \ + ptexdir/ptex-prntknj.test \ + ptexdir/ptex-ucs.test uptex_cppflags = $(PTEXENC_INCLUDES) $(AM_CPPFLAGS) $(ZLIB_INCLUDES) uptex_ldadd = libukanji.a $(pproglib) $(PTEXENC_LIBS) $(LDADD) $(ZLIB_LIBS) @@ -4511,23 +4534,23 @@ upweb_tests = uptexdir/upbibtex.test uptexdir/updvitype.test \ uptexdir/newjfm.test uptexdir/uparse.test uptexdir/gkhuge.test \ uptexdir/gk256.test euptex_CPPFLAGS = $(PTEXENC_INCLUDES) $(AM_CPPFLAGS) \ - -I$(srcdir)/libmd5 $(ZLIB_INCLUDES) $(am__append_135) + -I$(srcdir)/libmd5 $(ZLIB_INCLUDES) $(am__append_136) # With --enable-ipc, e-upTeX may need to link with -lsocket. euptex_LDADD = libukanji.a $(pproglib) $(PTEXENC_LIBS) $(LDADD) \ - $(ipc_socketlibs) libmd5.a $(ZLIB_LIBS) $(am__append_136) + $(ipc_socketlibs) libmd5.a $(ZLIB_LIBS) $(am__append_137) euptex_DEPENDENCIES = libukanji.a $(pproglib) $(PTEXENC_DEPEND) $(default_dependencies) libmd5.a $(ZLIB_DEPEND) # e-upTeX C sources euptex_c_h = euptexini.c euptex0.c euptexcoerce.h euptexd.h nodist_euptex_SOURCES = $(euptex_c_h) euptex-pool.c dist_euptex_SOURCES = euptexdir/euptexextra.c euptexdir/euptexextra.h \ - $(am__append_138) + $(am__append_139) # We must create euptexd.h and [eu]ptexdir/[eu]ptex_version.h before building the euptex_OBJECTS. euptex_prereq = euptexd.h etexdir/etex_version.h \ uptexdir/ptex_version.h euptexdir/eptex_version.h \ - uptexdir/uptex_version.h $(am__append_137) + uptexdir/uptex_version.h $(am__append_138) euptex_web_srcs = \ tex.web \ etexdir/etex.ch \ @@ -4572,6 +4595,9 @@ euptex_tests = \ @HITEX_TRUE@man1_MANS = hitexdir/man/hishrink.man hitexdir/man/histretch.man \ @HITEX_TRUE@ hitexdir/man/hitex.man + +# See hitex.am for comments about handling man. +@TEXPROF_TRUE@man1_MANS = texprofdir/man/texprof.man texprofdir/man/texprofile.man hitex_CPPFLAGS = $(AM_CPPFLAGS) $(ZLIB_INCLUDES) -I$(srcdir)/libmd5 \ -DINIT -DSTAT -DWEB2CVERSION="\"${WEB2CVERSION}\"" # -DDEBUG drops into an interactive debugging session. @@ -4660,7 +4686,7 @@ pdftex_dependencies = $(proglib) $(KPATHSEA_DEPEND) $(LIBPNG_DEPEND) \ # Force Automake to use CXXLD for linking nodist_EXTRA_pdftex_SOURCES = dummy.cxx pdf_tangle = WEBINPUTS=.:$(srcdir)/pdftexdir AM_V_P=$(AM_V_P) $(SHELL) ./tangle-sh $@ $(TANGLE) -pdftex_CPPFLAGS = $(pdftex_cppflags) $(am__append_139) +pdftex_CPPFLAGS = $(pdftex_cppflags) $(am__append_140) pdftex_CXXFLAGS = $(WARNING_CXXFLAGS) # With --enable-ipc, pdfTeX may need to link with -lsocket. @@ -4673,7 +4699,7 @@ pdftex_c_h = pdftexini.c pdftex0.c pdftexcoerce.h pdftexd.h nodist_pdftex_SOURCES = $(pdftex_c_h) pdftex-pool.c dist_pdftex_SOURCES = pdftexdir/pdftexextra.c pdftexdir/pdftexextra.h \ pdftexdir/pdftex_version.h pdftexdir/etex_version.h \ - $(am__append_140) + $(am__append_141) pdftex_ch_srcs = \ pdftexdir/pdftex.web \ pdftexdir/tex.ch0 \ @@ -5348,6 +5374,26 @@ libluaharfbuzz_a_SOURCES = \ luatexdir/luaharfbuzz/src/luaharfbuzz/variation.c libluajitharfbuzz_a_SOURCES = $(libluaharfbuzz_a_SOURCES) +texprof_CPPFLAGS = $(AM_CPPFLAGS) -I$(srcdir)/libmd5 -DINIT -DSTAT \ + -DWEB2CVERSION="\"${WEB2CVERSION}\"" +# -DDEBUG drops into an interactive debugging session. +texprof_LDADD = $(KPATHSEA_LIBS) libmd5.a +texprof_DEPENDENCIES = $(KPATHSEA_DEPEND) libmd5.a +# +texprofile_CPPFLAGS = $(AM_CPPFLAGS) +texprofile_LDADD = +texprofile_DEPENDENCIES = +# +# TeXprof CWEB sources +texprof_web = texprofdir/texprof.w +texprofile_web = texprofdir/texprofile.w + +# Creating several files: need stamp file and two rules with identical recipes +texprof_ctangle_sh = CWEBINPUTS=$(srcdir)/texprofdir AM_V_P=$(AM_V_P) $(SHELL) ./tangle-sh $@ $(CTANGLE) + +# For each cweb (.w) source file, list the files generated. +texprof_c = texprof.c +texprofile_c = texprofile.c # Force Automake to use CXXLD for linking nodist_EXTRA_xetex_SOURCES = dummy.cxx @@ -5356,18 +5402,18 @@ libxetex = libxetex.a xetex_cppflags = $(AM_CPPFLAGS) -I$(srcdir)/xetexdir $(ICU_INCLUDES) \ $(FREETYPE2_INCLUDES) $(TECKIT_INCLUDES) $(HARFBUZZ_INCLUDES) \ $(GRAPHITE2_INCLUDES) $(LIBPNG_INCLUDES) $(ZLIB_INCLUDES) \ - $(PPLIB_INCLUDES) -I$(srcdir)/libmd5 $(am__append_110) \ - $(am__append_112) + $(PPLIB_INCLUDES) -I$(srcdir)/libmd5 $(am__append_111) \ + $(am__append_113) xetex_ldadd = $(libxetex) $(HARFBUZZ_LIBS) $(GRAPHITE2_LIBS) \ $(ICU_LIBS) $(ICU_LIBS_EXTRA) $(TECKIT_LIBS) $(LIBPNG_LIBS) \ $(FREETYPE2_LIBS) $(PPLIB_LIBS) $(ZLIB_LIBS) libmd5.a \ - $(am__append_113) + $(am__append_114) xetex_dependencies = $(proglib) $(KPATHSEA_DEPEND) $(ICU_DEPEND) \ $(TECKIT_DEPEND) $(HARFBUZZ_DEPEND) $(GRAPHITE2_DEPEND) \ $(LIBPNG_DEPEND) $(FREETYPE2_DEPEND) $(ZLIB_DEPEND) \ $(PPLIB_DEPEND) libmd5.a @XETEX_MACOSX_TRUE@xetex_LDFLAGS = -framework ApplicationServices -framework Cocoa -xetex_CPPFLAGS = $(xetex_cppflags) $(am__append_141) +xetex_CPPFLAGS = $(xetex_cppflags) $(am__append_142) xetex_CFLAGS = $(WARNING_CFLAGS) xetex_CXXFLAGS = # $(WARNING_CXXFLAGS) xetex_LDADD = $(xetex_ldadd) $(LDADD) $(ipc_socketlibs) @@ -5376,7 +5422,7 @@ xetex_c_h = xetexini.c xetex0.c xetexcoerce.h xetexd.h nodist_xetex_SOURCES = $(xetex_c_h) xetex-pool.c dist_xetex_SOURCES = xetexdir/xetexextra.c xetexdir/xetexextra.h \ xetexdir/etex_version.h xetexdir/xetex_version.h \ - $(am__append_142) + $(am__append_143) xetex_ch_srcs = \ xetexdir/xetex.web \ xetexdir/tex.ch0 \ @@ -5410,7 +5456,7 @@ libxetex_a_SOURCES = xetexdir/XeTeXFontInst.cpp \ xetexdir/image/jpegimage.h xetexdir/image/mfileio.c \ xetexdir/image/mfileio.h xetexdir/image/numbers.c \ xetexdir/image/numbers.h xetexdir/image/pngimage.c \ - xetexdir/image/pngimage.h $(am__append_114) $(am__append_115) + xetexdir/image/pngimage.h $(am__append_115) $(am__append_116) # We must create xetexd.h etc. before building the libxetex_a_OBJECTS. libxetex_prereq = xetexd.h $(xetex_dependencies) @@ -5517,13 +5563,13 @@ aleph_tests = alephdir/aleph.test synctex_SOURCES = \ synctexdir/synctex_main.c -synctex_CPPFLAGS = -I$(srcdir)/synctexdir $(am__append_124) -synctex_LDADD = $(libsynctex) $(ZLIB_LIBS) $(am__append_125) +synctex_CPPFLAGS = -I$(srcdir)/synctexdir $(am__append_125) +synctex_LDADD = $(libsynctex) $(ZLIB_LIBS) $(am__append_126) libsynctex = $(LTLIBSYNCTEX) $(LIBSYNCTEX) libsynctex_la_CPPFLAGS = -I$(srcdir)/synctexdir $(ZLIB_INCLUDES) -DSYNCTEX_USE_LOCAL_HEADER libsynctex_a_CPPFLAGS = $(libsynctex_la_CPPFLAGS) libsynctex_la_LDFLAGS = -rpath @libdir@ -bindir @bindir@ -no-undefined -version-info $(SYNCTEX_LT_VERSINFO) -libsynctex_la_LIBADD = $(ZLIB_LIBS) $(am__append_126) +libsynctex_la_LIBADD = $(ZLIB_LIBS) $(am__append_127) libsynctex_la_SOURCES = \ synctexdir/synctex_parser.c \ synctexdir/synctex_parser_local.h \ @@ -5605,7 +5651,7 @@ all: ff-config.h .SUFFIXES: .c .cc .cin .cpp .cxx .h .hin .lo .log .mm .o .obj .p .pin .pl .pl$(EXEEXT) .test .test$(EXEEXT) .trs am--refresh: Makefile @: -$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../../am/dist_hook.am $(srcdir)/am/bootstrap.am $(srcdir)/am/web.am $(srcdir)/am/cweb.am $(srcdir)/am/texmf.am $(srcdir)/mfluadir/am/mflua.am $(srcdir)/mfluadir/am/mfluaotfcc.am $(srcdir)/mfluadir/am/mfluapotrace.am $(srcdir)/mfluadir/am/mflualpeg.am $(srcdir)/mfluajitdir/am/mfluajit.am $(srcdir)/mfluajitdir/am/mfluajitlpeg.am $(srcdir)/mplibdir/am/mplib.am $(srcdir)/pmpostdir/am/pmpost.am $(srcdir)/mplibdir/am/libmputil.am $(srcdir)/mplibdir/am/libmplib.am $(srcdir)/etexdir/am/etex.am $(srcdir)/ptexdir/am/ptex.am $(srcdir)/uptexdir/am/uptex.am $(srcdir)/euptexdir/am/euptex.am $(srcdir)/hitexdir/am/hitex.am $(srcdir)/pdftexdir/am/libpdftex.am $(srcdir)/pdftexdir/am/pdftex.am $(srcdir)/pdftexdir/am/ttf2afm.am $(srcdir)/pdftexdir/am/pdftosrc.am $(srcdir)/luatexdir/am/luasocket.am $(srcdir)/luatexdir/am/luamisc.am $(srcdir)/luatexdir/am/libunilib.am $(srcdir)/luatexdir/am/luafontforge.am $(srcdir)/luatexdir/am/libluatex.am $(srcdir)/luatexdir/am/luaffi.am $(srcdir)/luatexdir/am/luatex.am $(srcdir)/luatexdir/am/luaharfbuzz.am $(srcdir)/xetexdir/am/xetex.am $(srcdir)/omegaware/am/omegaware.am $(srcdir)/alephdir/am/aleph.am $(srcdir)/synctexdir/am/synctex.am $(srcdir)/libmd5/am/md5.am $(srcdir)/../../am/bin_links.am $(am__configure_deps) +$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(srcdir)/../../am/dist_hook.am $(srcdir)/am/bootstrap.am $(srcdir)/am/web.am $(srcdir)/am/cweb.am $(srcdir)/am/texmf.am $(srcdir)/mfluadir/am/mflua.am $(srcdir)/mfluadir/am/mfluaotfcc.am $(srcdir)/mfluadir/am/mfluapotrace.am $(srcdir)/mfluadir/am/mflualpeg.am $(srcdir)/mfluajitdir/am/mfluajit.am $(srcdir)/mfluajitdir/am/mfluajitlpeg.am $(srcdir)/mplibdir/am/mplib.am $(srcdir)/pmpostdir/am/pmpost.am $(srcdir)/mplibdir/am/libmputil.am $(srcdir)/mplibdir/am/libmplib.am $(srcdir)/etexdir/am/etex.am $(srcdir)/ptexdir/am/ptex.am $(srcdir)/uptexdir/am/uptex.am $(srcdir)/euptexdir/am/euptex.am $(srcdir)/hitexdir/am/hitex.am $(srcdir)/pdftexdir/am/libpdftex.am $(srcdir)/pdftexdir/am/pdftex.am $(srcdir)/pdftexdir/am/ttf2afm.am $(srcdir)/pdftexdir/am/pdftosrc.am $(srcdir)/luatexdir/am/luasocket.am $(srcdir)/luatexdir/am/luamisc.am $(srcdir)/luatexdir/am/libunilib.am $(srcdir)/luatexdir/am/luafontforge.am $(srcdir)/luatexdir/am/libluatex.am $(srcdir)/luatexdir/am/luaffi.am $(srcdir)/luatexdir/am/luatex.am $(srcdir)/luatexdir/am/luaharfbuzz.am $(srcdir)/texprofdir/am/texprof.am $(srcdir)/xetexdir/am/xetex.am $(srcdir)/omegaware/am/omegaware.am $(srcdir)/alephdir/am/aleph.am $(srcdir)/synctexdir/am/synctex.am $(srcdir)/libmd5/am/md5.am $(srcdir)/../../am/bin_links.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ @@ -5627,7 +5673,7 @@ Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles)'; \ cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__maybe_remake_depfiles);; \ esac; -$(srcdir)/../../am/dist_hook.am $(srcdir)/am/bootstrap.am $(srcdir)/am/web.am $(srcdir)/am/cweb.am $(srcdir)/am/texmf.am $(srcdir)/mfluadir/am/mflua.am $(srcdir)/mfluadir/am/mfluaotfcc.am $(srcdir)/mfluadir/am/mfluapotrace.am $(srcdir)/mfluadir/am/mflualpeg.am $(srcdir)/mfluajitdir/am/mfluajit.am $(srcdir)/mfluajitdir/am/mfluajitlpeg.am $(srcdir)/mplibdir/am/mplib.am $(srcdir)/pmpostdir/am/pmpost.am $(srcdir)/mplibdir/am/libmputil.am $(srcdir)/mplibdir/am/libmplib.am $(srcdir)/etexdir/am/etex.am $(srcdir)/ptexdir/am/ptex.am $(srcdir)/uptexdir/am/uptex.am $(srcdir)/euptexdir/am/euptex.am $(srcdir)/hitexdir/am/hitex.am $(srcdir)/pdftexdir/am/libpdftex.am $(srcdir)/pdftexdir/am/pdftex.am $(srcdir)/pdftexdir/am/ttf2afm.am $(srcdir)/pdftexdir/am/pdftosrc.am $(srcdir)/luatexdir/am/luasocket.am $(srcdir)/luatexdir/am/luamisc.am $(srcdir)/luatexdir/am/libunilib.am $(srcdir)/luatexdir/am/luafontforge.am $(srcdir)/luatexdir/am/libluatex.am $(srcdir)/luatexdir/am/luaffi.am $(srcdir)/luatexdir/am/luatex.am $(srcdir)/luatexdir/am/luaharfbuzz.am $(srcdir)/xetexdir/am/xetex.am $(srcdir)/omegaware/am/omegaware.am $(srcdir)/alephdir/am/aleph.am $(srcdir)/synctexdir/am/synctex.am $(srcdir)/libmd5/am/md5.am $(srcdir)/../../am/bin_links.am $(am__empty): +$(srcdir)/../../am/dist_hook.am $(srcdir)/am/bootstrap.am $(srcdir)/am/web.am $(srcdir)/am/cweb.am $(srcdir)/am/texmf.am $(srcdir)/mfluadir/am/mflua.am $(srcdir)/mfluadir/am/mfluaotfcc.am $(srcdir)/mfluadir/am/mfluapotrace.am $(srcdir)/mfluadir/am/mflualpeg.am $(srcdir)/mfluajitdir/am/mfluajit.am $(srcdir)/mfluajitdir/am/mfluajitlpeg.am $(srcdir)/mplibdir/am/mplib.am $(srcdir)/pmpostdir/am/pmpost.am $(srcdir)/mplibdir/am/libmputil.am $(srcdir)/mplibdir/am/libmplib.am $(srcdir)/etexdir/am/etex.am $(srcdir)/ptexdir/am/ptex.am $(srcdir)/uptexdir/am/uptex.am $(srcdir)/euptexdir/am/euptex.am $(srcdir)/hitexdir/am/hitex.am $(srcdir)/pdftexdir/am/libpdftex.am $(srcdir)/pdftexdir/am/pdftex.am $(srcdir)/pdftexdir/am/ttf2afm.am $(srcdir)/pdftexdir/am/pdftosrc.am $(srcdir)/luatexdir/am/luasocket.am $(srcdir)/luatexdir/am/luamisc.am $(srcdir)/luatexdir/am/libunilib.am $(srcdir)/luatexdir/am/luafontforge.am $(srcdir)/luatexdir/am/libluatex.am $(srcdir)/luatexdir/am/luaffi.am $(srcdir)/luatexdir/am/luatex.am $(srcdir)/luatexdir/am/luaharfbuzz.am $(srcdir)/texprofdir/am/texprof.am $(srcdir)/xetexdir/am/xetex.am $(srcdir)/omegaware/am/omegaware.am $(srcdir)/alephdir/am/aleph.am $(srcdir)/synctexdir/am/synctex.am $(srcdir)/libmd5/am/md5.am $(srcdir)/../../am/bin_links.am $(am__empty): $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) $(SHELL) ./config.status --recheck @@ -8239,6 +8285,14 @@ tex$(EXEEXT): $(tex_OBJECTS) $(tex_DEPENDENCIES) $(EXTRA_tex_DEPENDENCIES) @rm -f tex$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tex_OBJECTS) $(tex_LDADD) $(LIBS) +texprof$(EXEEXT): $(texprof_OBJECTS) $(texprof_DEPENDENCIES) $(EXTRA_texprof_DEPENDENCIES) + @rm -f texprof$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(texprof_OBJECTS) $(texprof_LDADD) $(LIBS) + +texprofile$(EXEEXT): $(texprofile_OBJECTS) $(texprofile_DEPENDENCIES) $(EXTRA_texprofile_DEPENDENCIES) + @rm -f texprofile$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(texprofile_OBJECTS) $(texprofile_LDADD) $(LIBS) + tftopl$(EXEEXT): $(tftopl_OBJECTS) $(tftopl_DEPENDENCIES) $(EXTRA_tftopl_DEPENDENCIES) @rm -f tftopl$(EXEEXT) $(AM_V_CCLD)$(LINK) $(tftopl_OBJECTS) $(tftopl_LDADD) $(LIBS) @@ -8548,6 +8602,8 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tex-tex0.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tex-texextra.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tex-texini.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/texprof-texprof.Po@am__quote@ # am--include-marker +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/texprofile-texprofile.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tftopl.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/tie-tie.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/twill.Po@am__quote@ # am--include-marker @@ -18162,6 +18218,34 @@ tex-tex-pool.obj: tex-pool.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tex_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o tex-tex-pool.obj `if test -f 'tex-pool.c'; then $(CYGPATH_W) 'tex-pool.c'; else $(CYGPATH_W) '$(srcdir)/tex-pool.c'; fi` +texprof-texprof.o: texprof.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(texprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT texprof-texprof.o -MD -MP -MF $(DEPDIR)/texprof-texprof.Tpo -c -o texprof-texprof.o `test -f 'texprof.c' || echo '$(srcdir)/'`texprof.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/texprof-texprof.Tpo $(DEPDIR)/texprof-texprof.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='texprof.c' object='texprof-texprof.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(texprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o texprof-texprof.o `test -f 'texprof.c' || echo '$(srcdir)/'`texprof.c + +texprof-texprof.obj: texprof.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(texprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT texprof-texprof.obj -MD -MP -MF $(DEPDIR)/texprof-texprof.Tpo -c -o texprof-texprof.obj `if test -f 'texprof.c'; then $(CYGPATH_W) 'texprof.c'; else $(CYGPATH_W) '$(srcdir)/texprof.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/texprof-texprof.Tpo $(DEPDIR)/texprof-texprof.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='texprof.c' object='texprof-texprof.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(texprof_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o texprof-texprof.obj `if test -f 'texprof.c'; then $(CYGPATH_W) 'texprof.c'; else $(CYGPATH_W) '$(srcdir)/texprof.c'; fi` + +texprofile-texprofile.o: texprofile.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(texprofile_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT texprofile-texprofile.o -MD -MP -MF $(DEPDIR)/texprofile-texprofile.Tpo -c -o texprofile-texprofile.o `test -f 'texprofile.c' || echo '$(srcdir)/'`texprofile.c +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/texprofile-texprofile.Tpo $(DEPDIR)/texprofile-texprofile.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='texprofile.c' object='texprofile-texprofile.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(texprofile_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o texprofile-texprofile.o `test -f 'texprofile.c' || echo '$(srcdir)/'`texprofile.c + +texprofile-texprofile.obj: texprofile.c +@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(texprofile_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT texprofile-texprofile.obj -MD -MP -MF $(DEPDIR)/texprofile-texprofile.Tpo -c -o texprofile-texprofile.obj `if test -f 'texprofile.c'; then $(CYGPATH_W) 'texprofile.c'; else $(CYGPATH_W) '$(srcdir)/texprofile.c'; fi` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/texprofile-texprofile.Tpo $(DEPDIR)/texprofile-texprofile.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='texprofile.c' object='texprofile-texprofile.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(texprofile_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o texprofile-texprofile.obj `if test -f 'texprofile.c'; then $(CYGPATH_W) 'texprofile.c'; else $(CYGPATH_W) '$(srcdir)/texprofile.c'; fi` + tie-tie.o: tie.c @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(tie_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT tie-tie.o -MD -MP -MF $(DEPDIR)/tie-tie.Tpo -c -o tie-tie.o `test -f 'tie.c' || echo '$(srcdir)/'`tie.c @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/tie-tie.Tpo $(DEPDIR)/tie-tie.Po @@ -19838,6 +19922,8 @@ distclean: distclean-recursive -rm -f ./$(DEPDIR)/tex-tex0.Po -rm -f ./$(DEPDIR)/tex-texextra.Po -rm -f ./$(DEPDIR)/tex-texini.Po + -rm -f ./$(DEPDIR)/texprof-texprof.Po + -rm -f ./$(DEPDIR)/texprofile-texprofile.Po -rm -f ./$(DEPDIR)/tftopl.Po -rm -f ./$(DEPDIR)/tie-tie.Po -rm -f ./$(DEPDIR)/twill.Po @@ -20614,6 +20700,8 @@ maintainer-clean: maintainer-clean-recursive -rm -f ./$(DEPDIR)/tex-tex0.Po -rm -f ./$(DEPDIR)/tex-texextra.Po -rm -f ./$(DEPDIR)/tex-texini.Po + -rm -f ./$(DEPDIR)/texprof-texprof.Po + -rm -f ./$(DEPDIR)/texprofile-texprofile.Po -rm -f ./$(DEPDIR)/tftopl.Po -rm -f ./$(DEPDIR)/tie-tie.Po -rm -f ./$(DEPDIR)/twill.Po @@ -21928,7 +22016,10 @@ ptex.web: tie$(EXEEXT) $(ptex_web_srcs) ptex.ch: tie$(EXEEXT) ptex.web $(ptex_ch_srcs) $(tie_c) ptex.web $(ptex_ch_srcs) ptexdir/ptriptest.log: ptex$(EXEEXT) dvitype$(EXEEXT) pltotf$(EXEEXT) tftopl$(EXEEXT) -ptexdir/pver.log ptexdir/wcfname.log: ptex$(EXEEXT) +ptexdir/pver.log ptexdir/wcfname.log \ + ptexdir/ptex-ctrlsym.log ptexdir/ptex-prntknj.log \ + ptexdir/ptex-ucs.log: ptex$(EXEEXT) + ptrip.diffs: ptex$(EXEEXT) dvitype$(EXEEXT) pltotf$(EXEEXT) tftopl$(EXEEXT) $(triptrap_diffs) $@ .PHONY: ptrip-clean @@ -22011,6 +22102,7 @@ uptexdir/sample.log: updvitype$(EXEEXT) uptexdir/yokotate.log uptexdir/skipjfmp.log \ uptexdir/newjfm.log uptexdir/uparse.log \ uptexdir/gkhuge.log uptexdir/gk256.log: uppltotf$(EXEEXT) uptftopl$(EXEEXT) + uptrip.diffs: uptex$(EXEEXT) dvitype$(EXEEXT) pltotf$(EXEEXT) tftopl$(EXEEXT) $(triptrap_diffs) $@ .PHONY: uptrip-clean @@ -22240,6 +22332,40 @@ luatexdir/luajithbtex.log luatexdir/luajithbimage.log: luajithbtex$(EXEEXT) $(libluaharfbuzz_a_OBJECTS): $(LUA_DEPEND) $(libluajitharfbuzz_a_OBJECTS): $(LUAJIT_DEPEND) + +# convenience target to build all the programs here. +@TEXPROF_TRUE@texprofall: texprof texprofile + +$(texprof_c): texprof-tangle +$(texprofile_c): texprofile-tangle + +# +texprof-tangle: ctangle$(EXEEXT) texprofdir/texprof.w tangle-sh + $(texprof_ctangle_sh) texprof + +texprofile-tangle: ctangle$(EXEEXT) texprofdir/texprofile.w tangle-sh + $(texprof_ctangle_sh) texprofile + +# +#texprof_tests = texprofdir/tests/hello.test \ +# texprofdir/tests/rule.test +# +#texprofdir/tests/hello.log: texprof$(EXEEXT) histretch$(EXEEXT) +#texprofdir/tests/rule.log: texprof$(EXEEXT) histretch$(EXEEXT) hishrink$(EXEEXT) +# +#EXTRA_DIST += $(texprof_tests) +# +#if TEXPROF +#TESTS += $(texprof_tests) +#endif TEXPROF +# +#EXTRA_DIST += texprofdir/tests/hello.tex +#DISTCLEANFILES += hello.log + +#EXTRA_DIST += texprofdir/tests/rule.tex +#DISTCLEANFILES += rule.log + +# (end of texprof.am) $(xetex_OBJECTS): $(xetex_prereq) $(xetex_c_h): xetex-web2c diff --git a/source/texk/web2c/ac/web2c.ac b/source/texk/web2c/ac/web2c.ac index 9901c93c4..471c3250f 100644 --- a/source/texk/web2c/ac/web2c.ac +++ b/source/texk/web2c/ac/web2c.ac @@ -43,6 +43,7 @@ m4_define([kpse_tex_progs], [dnl [[luajithbtex], [yes], [], [LuaHBJITTeX], [pplib libpng zziplib luajit harfbuzz]], [[mp], [yes], [], [MetaPost], [mpfi mpfr cairo libpng]], [[pmp], [yes], [], [pMetaPost], [mpfi mpfr cairo libpng ptexenc]], +[[texprof], [yes], [], [TeXprof], []], [[upmp], [yes], [], [upMetaPost], [mpfi mpfr cairo libpng ptexenc]], [[xetex], [yes], [yes], [XeTeX], [pplib libpng freetype2 teckit harfbuzz]], ])[]dnl diff --git a/source/texk/web2c/bibtex.ch b/source/texk/web2c/bibtex.ch index c8d566ee6..b9661c65c 100644 --- a/source/texk/web2c/bibtex.ch +++ b/source/texk/web2c/bibtex.ch @@ -13,6 +13,12 @@ % 03/09/90 `int' is a bad variable name for C. % (more recent changes in the ChangeLog) +@x [0] +\def\(#1){} % this is used to make section names sort themselves better +@y +\def\({} % this is used to make section names sort themselves better +@z + % [0] Let bibtex.tex work with latest webmac (which defines \ET, hence % making E active loses). @x @@ -104,7 +110,7 @@ begin initialize; print_ln(banner);@/ @y -@ +@ begin standard_input := stdin; standard_output := stdout; @@ -1633,7 +1639,7 @@ itself will get a new section number. @y @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) -@ = +@ = procedure parse_arguments; const n_options = 4; {Pascal won't count array lengths for us.} var @!long_options: array[0..n_options] of getopt_struct; diff --git a/source/texk/web2c/configure b/source/texk/web2c/configure index 7f9c194d1..1b30570db 100755 --- a/source/texk/web2c/configure +++ b/source/texk/web2c/configure @@ -800,6 +800,8 @@ XETEX_FALSE XETEX_TRUE UPMP_FALSE UPMP_TRUE +TEXPROF_FALSE +TEXPROF_TRUE PMP_FALSE PMP_TRUE MP_FALSE @@ -1047,6 +1049,7 @@ enable_luahbtex enable_luajithbtex enable_mp enable_pmp +enable_texprof enable_upmp enable_xetex enable_xetex_synctex @@ -1792,6 +1795,7 @@ Optional Features: --disable-luajithbtex do not compile and install LuaHBJITTeX --disable-mp do not compile and install MetaPost --disable-pmp do not compile and install pMetaPost + --disable-texprof do not compile and install TeXprof --disable-upmp do not compile and install upMetaPost --disable-xetex do not compile and install XeTeX --disable-xetex-synctex build XeTeX without SyncTeX support @@ -20811,6 +20815,17 @@ test "x$enable_web2c:$enable_pmp" = xyes:yes && { need_libpng=yes need_ptexenc=yes } +# Check whether --enable-texprof was given. +if test ${enable_texprof+y} +then : + enableval=$enable_texprof; +fi +case $enable_texprof in #( + yes | no) : + ;; #( + *) : + enable_texprof=yes ;; +esac # Check whether --enable-upmp was given. if test ${enable_upmp+y} then : @@ -23600,6 +23615,13 @@ fi else PMP_TRUE='#' PMP_FALSE= +fi + if test "x$enable_texprof" = xyes; then + TEXPROF_TRUE= + TEXPROF_FALSE='#' +else + TEXPROF_TRUE='#' + TEXPROF_FALSE= fi if test "x$enable_upmp" = xyes; then UPMP_TRUE= @@ -29657,6 +29679,10 @@ if test -z "${PMP_TRUE}" && test -z "${PMP_FALSE}"; then as_fn_error $? "conditional \"PMP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi +if test -z "${TEXPROF_TRUE}" && test -z "${TEXPROF_FALSE}"; then + as_fn_error $? "conditional \"TEXPROF\" was never defined. +Usually this means the macro was only invoked conditionally." "$LINENO" 5 +fi if test -z "${UPMP_TRUE}" && test -z "${UPMP_FALSE}"; then as_fn_error $? "conditional \"UPMP\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 diff --git a/source/texk/web2c/cwebdir/ChangeLog b/source/texk/web2c/cwebdir/ChangeLog index 7bb172129..ecd275ac3 100644 --- a/source/texk/web2c/cwebdir/ChangeLog +++ b/source/texk/web2c/cwebdir/ChangeLog @@ -1,3 +1,13 @@ +2024-09-14 Andreas Scherer + + * ctwill-mini.c, + * ctwill-w2c.ch, + * cweav-w2c.ch, + * cweave.w, + * cwebacromac.tex, + * cwebmac.tex, + * refsort.ch: Fix sorting order in Names-of-the-Sections. + 2024-08-12 Andreas Scherer * Makefile diff --git a/source/texk/web2c/cwebdir/ctwill-mini.ch b/source/texk/web2c/cwebdir/ctwill-mini.ch index c5f7a3df8..80e8feb35 100644 --- a/source/texk/web2c/cwebdir/ctwill-mini.ch +++ b/source/texk/web2c/cwebdir/ctwill-mini.ch @@ -1589,9 +1589,9 @@ Section 212--213. Section 215. @x -@={@+ int count=-1; /* characters remaining before string break */ +@={@+ int count=-1; /* characters remaining before string break */ @y -@={int count=-1; /* characters remaining before string break */ +@={@+ int count=-1; /* characters remaining before string break */ @z Section 220. @@ -1819,12 +1819,12 @@ Section 247. @x @ @d usage_sentinel (struct perm_meaning *)1 -@= { +@= { @y @ @d usage_sentinel (struct perm_meaning *)1 @-usage_sentinel@> @$usage_sentinel {CTWILL}247 =(\&{struct} \&{perm\_meaning} ${}{*}{}$) \T{1}@> -@=@+ { +@= { @z Section 251. @@ -1851,9 +1851,9 @@ Section 252. Section 254. @x -@ @= { +@ @= { @y -@r @ @= { +@r @ @= { @z Section 255. diff --git a/source/texk/web2c/cwebdir/ctwill-w2c.ch b/source/texk/web2c/cwebdir/ctwill-w2c.ch index 664254dee..d421c3f78 100644 --- a/source/texk/web2c/cwebdir/ctwill-w2c.ch +++ b/source/texk/web2c/cwebdir/ctwill-w2c.ch @@ -466,7 +466,7 @@ beginning of phase two. We initialize the output variables in a slightly tricky way so that the first line of the output file will be `\.{\\input cwebmac}'. -@= +@= out_ptr=out_buf+1; out_line=1; active_file=tex_file; tex_printf("\\input cwebma"); *out_ptr='c'; @y @@ -486,7 +486,7 @@ debugging mini-index entries. @d proofing flags['P'] -@= +@= out_ptr=out_buf+1; out_line=1; active_file=tex_file; tex_puts("\\input "); tex_printf(use_language); @@ -952,7 +952,7 @@ section_count=0; format_visible=true; right_start_switch=false; copy_limbo(); @x [12.229] l.4212 static boolean group_found=false; /* has a starred section occurred? */ -@ @= { +@ @= { section_count++; @y static boolean group_found=false; /* has a starred section occurred? */ @@ -960,7 +960,7 @@ static boolean right_start_switch; /* has `\.{@@r}' occurred recently? */ static boolean temp_switch; /* has `\.{@@\%}' occurred recently? */ @ @d usage_sentinel (struct perm_meaning *)1 -@= { +@= { section_count++; temp_switch=false; temp_meaning_ptr=temp_meaning_stack; top_usage=usage_sentinel; @@ -1040,9 +1040,9 @@ flush_buffer(out_ptr,false,false); @z @x [12.236] l.4340 -@= { +@= { @y -@= { +@= { is_macro=true; @z @@ -1073,10 +1073,10 @@ flush_buffer(out_ptr,false,false); @z @x [12.237] l.4369 -@ @= { +@ @= { doing_format=true; @y -@ @= { +@ @= { doing_format=true; is_macro=false; @z diff --git a/source/texk/web2c/cwebdir/cweav-w2c.ch b/source/texk/web2c/cwebdir/cweav-w2c.ch index 6d350fc40..b0adceab7 100644 --- a/source/texk/web2c/cwebdir/cweav-w2c.ch +++ b/source/texk/web2c/cwebdir/cweav-w2c.ch @@ -195,7 +195,7 @@ beginning of phase two. We initialize the output variables in a slightly tricky way so that the first line of the output file will be `\.{\\input cwebmac}'. -@= +@= out_ptr=out_buf+1; out_line=1; active_file=tex_file; tex_printf("\\input cwebma"); *out_ptr='c'; @y @@ -210,7 +210,7 @@ prepended to `\.{cwebmac.tex}', e.g., if you call \.{CWEAVE} with Without this option the first line of the output file will be `\.{\\input cwebmac}'. -@= +@= out_ptr=out_buf+1; out_line=1; active_file=tex_file; tex_puts("\\input "); tex_printf(use_language); diff --git a/source/texk/web2c/cwebdir/cweave.w b/source/texk/web2c/cwebdir/cweave.w index 627fa1fa8..015a3183b 100644 --- a/source/texk/web2c/cwebdir/cweave.w +++ b/source/texk/web2c/cwebdir/cweave.w @@ -93,7 +93,7 @@ char **av) /* argument values */ program=cweave; @@; common_init(); - @@; + @@; if (show_banner) puts(banner); /* print a ``banner line'' */ @@; phase_one(); /* read all the user's text and store the cross-references */ @@ -1076,9 +1076,9 @@ phase_one(void) { printf("*%d",(int)section_count); update_terminal(); /* print a progress report */ } - @@; - @@; - @@; + @@; + @@; + @@; if (changed_section[section_count]) change_exists=true; } @@ -1155,7 +1155,7 @@ the identifiers in \CEE/ texts enclosed in \pb, or for control texts enclosed in \.{@@\^}$\,\ldots\,$\.{@@>} or \.{@@.}$\,\ldots\,$\.{@@>} or \.{@@:}$\,\ldots\,$\.{@@>}. -@= +@= while (true) { switch (next_control=skip_TeX()) { case translit_code: err_print("! Use @@l in limbo only"); continue; @@ -1204,7 +1204,7 @@ static name_pointer res_wd_end; /* pointer to the first nonreserved identifier * @ When we get to the following code we have |next_control>=format_code|. -@= +@= while (next_control<=definition) { /* |format_code| or |definition| */ if (next_control==definition) { xref_switch=def_flag; /* implied \.{@@!} */ @@ -1261,7 +1261,7 @@ else { @ Finally, when the \TEX/ and definition parts have been treated, we have |next_control>=begin_C|. -@= +@= if (next_control<=section_name) { /* |begin_C| or |section_name| */ if (next_control==begin_C) section_xref_switch=0; else { @@ -1398,7 +1398,7 @@ beginning of phase two. We initialize the output variables in a slightly tricky way so that the first line of the output file will be `\.{\\input cwebmac}'. -@= +@= out_ptr=out_buf+1; out_line=1; active_file=tex_file; tex_printf("\\input cwebma"); *out_ptr='c'; @@ -3420,10 +3420,10 @@ switch (next_control) { app_scrap(section_scrap,maybe_math);@+ app_scrap(exp,yes_math);@+break; case string: case constant: case verbatim: - @@;@+break; + @@;@+break; case identifier: app_cur_id(true);@+break; case TeX_string: - @@;@+break; + @@;@+break; case '/': case '.': app(next_control);@+app_scrap(binop,yes_math);@+break; case '<': app_str("\\langle");@+app_scrap(prelangle,yes_math);@+break; @@ -3545,7 +3545,7 @@ Many of the special characters in a string must be prefixed by `\.\\' so that \TEX/ will print them properly. @^special string characters@> -@={@+ int count=-1; /* characters remaining before string break */ +@={@+ int count=-1; /* characters remaining before string break */ switch (next_control) { case constant: app_str("\\T{"@q}@>); break; @.\\T@> @@ -3611,7 +3611,7 @@ this bug is probably to enclose the \.{@@t...@@>} in \.{@@[...@@]} so that the \TEX/ string is treated as an expression. @^bug, known@> -@= +@= app_str("\\hbox{"@q}@>); @^high-bit character handling@> while (id_first@; +while (!input_has_ended) @@; } @ @=@+static void phase_two(void); @@ -4211,13 +4211,13 @@ static boolean format_visible; /* should the next format declaration be output? static boolean doing_format=false; /* are we outputting a format declaration? */ static boolean group_found=false; /* has a starred section occurred? */ -@ @= { +@ @= { section_count++; @@; save_position(); - @@; - @@; - @@; + @@; + @@; + @@; @@; @@; } @@ -4257,7 +4257,7 @@ out('{'); out_section(section_count); out('}'); @ In the \TEX/ part of a section, we simply copy the source text, except that index entries are not copied and \CEE/ text within \pb\ is translated. -@= do +@= do switch (next_control=copy_TeX()) { case '|': init_stack(); output_C(); break; case '@@': out('@@'); break; @@ -4279,12 +4279,12 @@ while (next_control=format_code|, and the token memory is in its initial empty state. -@= +@= space_checked=false; while (next_control<=definition) { /* |format_code| or |definition| */ init_stack(); - if (next_control==definition) @@; - else @@; + if (next_control==definition) @@; + else @@; outer_parse(); finish_C(format_visible); format_visible=true; doing_format=false; } @@ -4337,7 +4337,7 @@ if the identifier is not followed by `\.(' at all, the replacement text starts immediately after the identifier. In the former case, it starts after we scan the matching `\.)'. -@= { +@= { if (save_line!=out_line || save_place!=out_ptr || space_checked) app(backup); if(!space_checked){emit_space_if_needed();save_position();} app_str("\\D"); /* this will produce `\#\&{define }' */ @@ -4366,7 +4366,7 @@ it starts after we scan the matching `\.)'. } } -@ @= { +@ @= { doing_format=true; if(*(loc-1)=='s' || *(loc-1)=='S') format_visible=false; if(!space_checked){emit_space_if_needed();save_position();} @@ -4394,7 +4394,7 @@ point to the current section name, if it has a name. @= static name_pointer this_section; /* the current section name, or zero */ -@ @= +@ @= this_section=name_dir; if (next_control<=section_name) { emit_space_if_needed(); init_stack(); diff --git a/source/texk/web2c/cwebdir/cwebacromac.tex b/source/texk/web2c/cwebdir/cwebacromac.tex index 3e8baad77..1743ddd95 100644 --- a/source/texk/web2c/cwebdir/cwebacromac.tex +++ b/source/texk/web2c/cwebdir/cwebacromac.tex @@ -17,6 +17,16 @@ \let\pdfoutput=\outputmode \fi % end of LuaTeX->pdfTeX redirection macros +\def\pdfURL#1#2{\ifpdf \ifpdflua\pdfannotlink height \theheight depth \thedepth + attr {/Border [0 0 0]} user { /Type /Annot /Subtype /Link /A + << /S /URI /URI (#2) >>}\Blue #1\Black \pdfendlink % changed in 3.69 + \else {\setbox0=\hbox{\special{pdf: bc [ \pdflinkcolor ]}{#1}% + \special{pdf: ec}}\special{pdf: ann width \thewidth height \theheight + depth \thedepth << /Border [0 0 0] /Type /Annot /Subtype /Link /A + << /S /URI /URI (#2) >> >>}\box0\relax}\fi + \else #1 ({\tt#2})\fi} +{\catcode`\~=12 \gdef\TILDE/{~}} % ~ in a URL +{\catcode`\_=12 \gdef\UNDER/{_}} % _ in a URL \def\tocpages{1} % Most programs have one-page Table-of-Contents \def\startpdf{\def\pagemode{/PageMode /UseOutlines} \ifnum\contentspagenumber=0 \advance \pageno by -\tocpages @@ -66,8 +76,7 @@ \fi \else \addtokens\toksC{\the\toksD}\global\havenumtrue \fi - \next -} + \next} \def\makenote{\addtokens\toksB {\noexpand\pdflink{\the\toksC}}\toksC={}\global\havenumfalse} \def\maketoksdone{\edef\st{\global\noexpand\toksA={\the\toksB}}\st} @@ -99,6 +108,7 @@ \afterassignment\makeolproctok\let\nxt= } \def\makeolnexttok{\afterassignment\makeolproctok\let\nxt= } \def\makeolgobbletok{\afterassignment\makeolnexttok\let\nxt= } +\def\makeolgobbletokk{\afterassignment\makeolgobbletok\let\nxt= } \def\addF#1{\addtokens\toksF{#1}\tokprocessedtrue} % now comes a routine to "sanitize" section names, for pdf outlines \def\makeolproctok{\tokprocessedfalse @@ -109,8 +119,7 @@ \else\ifx^\nxt \addF^\else\ifx_\nxt \addF_% sanitize ^ and _ \else\ifx\nxt\spacechar \addF\space \else\if\noexpand\nxt\relax % we have a control sequence; is it one we know? - \ifx\nxt~\addF\space - \else\ifx\nxt\onespace\addF\space + \ifx\nxt~\addF\space \else\ifx\nxt\onespace\addF\space \else\the\sanitizer \iftokprocessed\else\makeolproctokctli \iftokprocessed\else\makeolproctokctlii @@ -124,8 +133,7 @@ \else\expandafter\makeolproctokchar\meaning\nxt \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi \fi\fi\fi - \next -} + \next} \def\makeolproctokchar#1 #2 #3{\addF{#3}} \def\makeolproctokctli{% \ifx\nxt\CEE\addF{C}\let\next\makeolgobbletok % \CEE/ @@ -133,8 +141,9 @@ \else\ifx\nxt\TEX\addF{TeX}\let\next\makeolgobbletok % \TEX/ \else\ifx\nxt\TeX\addF{TeX}\else\ifx\nxt\LaTeX\addF{LaTeX}% \else\ifx\nxt\CPLUSPLUS\addF{C++}\let\next\makeolgobbletok % \CPLUSPLUS/ - \else\ifx\nxt\Cee\addF{C}% + \else\ifx\nxt\Cee\addF{C}\else\ifx\nxt\dots\addF{...\space}% \else\ifx\nxt\PB \let\next\makeolgobbletok \tokprocessedtrue % \PB{...} + \else\ifx\nxt\9 \expandafter\nxt\relax \let\next\makeolgobbletokk % \9{#1} \else\ifx\nxt\.\tokprocessedtrue\instrtrue % \.{...} % skip \| \else\ifx\nxt\\\ifinstr\addF{\bschar\bschar}\else\tokprocessedtrue\fi @@ -149,7 +158,7 @@ \else\ifx\nxt\PP\addF{++}\else\ifx\nxt\MM\addF{--}% \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi \fi\fi\fi\fi\fi - \fi\fi + \fi\fi\fi\fi } \def\makeolproctokctlii{% \ifx\nxt\MG\addF{->}\else\ifx\nxt\GG\addF{>>}% diff --git a/source/texk/web2c/cwebdir/cwebmac.tex b/source/texk/web2c/cwebdir/cwebmac.tex index a46dc4b78..53454300a 100644 --- a/source/texk/web2c/cwebdir/cwebmac.tex +++ b/source/texk/web2c/cwebdir/cwebmac.tex @@ -132,16 +132,6 @@ \def\Blue{\pdfliteral{\pdflinkcolor\space rg \pdflinkcolor\space RG}} \fi \input cwebacromac % load hypertext macros -\def\pdfURL#1#2{\ifpdf \ifpdflua\pdfannotlink height \theheight depth \thedepth - attr {/Border [0 0 0]} user { /Type /Annot /Subtype /Link /A - << /S /URI /URI (#2) >>}\Blue #1\Black \pdfendlink % changed in 3.69 - \else {\setbox0=\hbox{\special{pdf: bc [ \pdflinkcolor ]}{#1}% - \special{pdf: ec}}\special{pdf: ann width \thewidth height \theheight - depth \thedepth << /Border [0 0 0] /Type /Annot /Subtype /Link /A - << /S /URI /URI (#2) >> >>}\box0\relax}\fi - \else #1 ({\tt#2})\fi} -{\catcode`\~=12 \gdef\TILDE/{~}} % ~ in a URL -{\catcode`\_=12 \gdef\UNDER/{_}} % _ in a URL \def\lapstar{\rlap{*}} \def\stsec{\rightskip=0pt % get out of C mode (cf. \B) @@ -242,9 +232,8 @@ \def\p#1{\cdot 2^{#1}} % power of two (hex exponent) \def\onmaybe{\let\ifon=\maybe} \let\maybe=\iftrue -\newif\ifon \newif\iftitle \newif\ifpagesaved +\newif\ifon \newif\iftitle \newif\ifpagesaved \newif\ifheader -\newif\ifheader \def\lheader{\headertrue\mainfont\the\pageno\eightrm\qquad\grouptitle \hfill\title\qquad\mainfont\topsecno} % top line on left-hand pages \def\rheader{\headertrue\mainfont\topsecno\eightrm\qquad\title\hfill diff --git a/source/texk/web2c/cwebdir/refsort.ch b/source/texk/web2c/cwebdir/refsort.ch index 67175b030..2ebedfca6 100644 --- a/source/texk/web2c/cwebdir/refsort.ch +++ b/source/texk/web2c/cwebdir/refsort.ch @@ -45,12 +45,24 @@ int main() item *x, **y; @z +@x [4] l.83 + @; +@y + @; +@z + @x [5] l.89 variable not used { register int k; @y { @z +@x [6] l.99 +@= +@y +@= +@z + @x [9] l.149 'register' removed in C++17 { register int toggle=0; @y diff --git a/source/texk/web2c/dvicopy.ch b/source/texk/web2c/dvicopy.ch index 5b4ebbc54..07b326164 100644 --- a/source/texk/web2c/dvicopy.ch +++ b/source/texk/web2c/dvicopy.ch @@ -8,45 +8,45 @@ % Mar 20 91 THD Updated to dvicopy 1.2 % (more recent changes in the ChangeLog) -@x [0] l.59 WEAVE: print changes only +@x [0] l.60 WEAVE: print changes only \pageno=\contentspagenumber \advance\pageno by 1 @y \pageno=\contentspagenumber \advance\pageno by 1 \let\maybe=\iffalse @z -@x [1] l.97 Define my_name +@x [1] l.98 Define my_name @d banner=='This is DVIcopy, Version 1.6' {printed when the program starts} @y @d my_name=='dvicopy' @d banner=='This is DVIcopy, Version 1.6' {printed when the program starts} @z -@x [2] l.123 No random reading on stdin, may be not seekable. +@x [2] l.124 No random reading on stdin, may be not seekable. @d random_reading==true {should we skip around in the file?} @y @= @!random_reading:boolean; {should we skip around in the file?} @z -@x [3] l.134 Purge non-local 'goto'. +@x [3] l.135 Purge non-local 'goto'. calls the `|jump_out|' procedure, which goes to the label |final_end|. @d final_end = 9999 {go here to wrap it up} @y calls the `|jump_out|' procedure. @z -@x [3] l.140 +@x [3] l.141 label final_end; @y @z -@x [3] l.145 Set up kpathsea. +@x [3] l.146 Set up kpathsea. procedure initialize; {this procedure gets things started properly} var @@/ begin print_ln(banner);@/ @y -@ +@ procedure initialize; {this procedure gets things started properly} var @@/ begin @@ -55,7 +55,7 @@ procedure initialize; {this procedure gets things started properly} print (banner); print_ln (version_string); @z -@x [5] l.177 Big enough arrays to convert the dvilj sample font document. +@x [5] l.178 Big enough arrays to convert the dvilj sample font document. @= @!max_fonts=100; {maximum number of distinct fonts} @!max_chars=10000; {maximum number of different characters among all fonts} @@ -85,7 +85,7 @@ procedure initialize; {this procedure gets things started properly} % [7] Rename the integer types, as they collide with names used by C99. % Rather than change the code all over the place, we use macros to do % the renaming. This could also be done at C preprocessor level. -@x l.244 +@x l.245 @d int_32 == integer {signed 32~bit integers} @y @d int_32 == integer {signed 32~bit integers} @@ -103,7 +103,7 @@ procedure initialize; {this procedure gets things started properly} % [11] Redirect output, so it can go to either stdout or stderr, % depending on where the output dvi file is going. -@x l.310 +@x l.311 @d print(#)==write(output,#) @d print_ln(#)==write_ln(output,#) @d new_line==write_ln(output) {start new line} @@ -113,7 +113,7 @@ procedure initialize; {this procedure gets things started properly} @d new_line==write_ln(term_out) {start new line} @z -@x [14] l.379 Permissive input. +@x [14] l.380 Permissive input. @!ASCII_code=" ".."~"; {a subrange of the integers} @y @!ASCII_code=0..255; {a subrange of the integers} @@ -122,7 +122,7 @@ procedure initialize; {this procedure gets things started properly} % [15] The text_char type is used as an array index into xord. The % default type `char' produces signed integers, which are bad array % indices in C. -@x l.399 +@x l.400 @d text_char == char {the data type of characters in text files} @d first_text_char=0 {ordinal number of the smallest element of |text_char|} @d last_text_char=127 {ordinal number of the largest element of |text_char|} @@ -132,7 +132,7 @@ procedure initialize; {this procedure gets things started properly} @d last_text_char=255 {ordinal number of the largest element of |text_char|} @z -@x [23] l.572 Remove non-local goto, declare jump_out as noreturn +@x [23] l.573 Remove non-local goto, declare jump_out as noreturn so a procedure called |jump_out| has been introduced. This procedure, which transfers control to the label |final_end| at the end of the program, contains the only non-local |@!goto| statement in \.{\title}. @@ -143,7 +143,7 @@ by a call on some system procedure that quietly terminates the program. @y so a procedure called |jump_out| has been introduced. @z -@x [23] l.581 +@x [23] l.582 @d abort(#)==begin print_ln(' ',#,'.'); jump_out; end @@ -170,31 +170,31 @@ uexit(1); end; @z -@x [24] l.596 Declare confusion as noreturn +@x [24] l.597 Declare confusion as noreturn says |confusion(|indication of where we are|)|. @y says |confusion|(indication of where we are). @z -@x [24] l.599 +@x [24] l.600 procedure confusion(@!p:pckt_pointer); @y noreturn procedure confusion(@!p:pckt_pointer); @z -@x [25] l.608 Declare overflow as noreturn +@x [25] l.609 Declare overflow as noreturn procedure overflow(@!p:pckt_pointer;@!n:int_16u); @y noreturn procedure overflow(@!p:pckt_pointer;@!n:int_16u); @z -@x [62] l.1235 cur_name is no longer a fixed-size array. +@x [62] l.1236 cur_name is no longer a fixed-size array. @!cur_name:packed array[1..name_length] of char; {external name, with no lower case letters} @y @!cur_name:^char; @z -@x [63] l.1240 Ignore arguments to make_font_name. +@x [63] l.1241 Ignore arguments to make_font_name. @ For \.{TFM} and \.{VF} files we just append the appropriate extension to the file name packet; in addition a system dependent area part (usually different for \.{TFM} and \.{VF} files) is prepended if @@ -229,24 +229,24 @@ to |make_font_name|. % [67] No conversion of filenames in lower case, and initialize and % terminate for C strings. Eliminate now unused variable. -@x l.1310 +@x l.1311 @!c:char; {a character to be appended to |cur_name|} @y @z -@x [67] l.1312 +@x [67] l.1313 cur_loc:=pckt_start[n]; cur_limit:=pckt_start[n+1]; @y cur_name := xmalloc_array (char, pckt_length (n) + pckt_length (e)); cur_loc:=pckt_start[n]; cur_limit:=pckt_start[n+1]; @z -@x [67] l.1317 +@x [67] l.1318 if (b>="a")and(b<="z") then Decr(b)(("a"-"A")); {convert to upper case} @y @z -@x [67] l.1320 +@x [67] l.1321 cur_loc:=pckt_start[e]; cur_limit:=pckt_start[e+1]; while cur_loc= TFM_default_area:=TFM_default_area_name; @y @ (No initialization to be done. Keep this module to preserve numbering.) @z -@x [94] l.1738 Declare bad_tfm as noreturn +@x [94] l.1739 Declare bad_tfm as noreturn procedure bad_tfm; @y noreturn procedure bad_tfm; @z -@x [94] l.1745 Declare bad_font as noreturn +@x [94] l.1746 Declare bad_font as noreturn procedure bad_font; @y noreturn procedure bad_font; @z -@x [95] l.1757 Open TFM file +@x [95] l.1758 Open TFM file @= make_font_name(TFM_default_area_name_length)(TFM_default_area)(tfm_ext); reset(tfm_file,cur_name); @@ -318,7 +318,7 @@ if full_name then begin end else @z -@x [104] l.1990 Compute alpha and beta. +@x [104] l.1991 Compute alpha and beta. alpha:=16; while z>=@'40000000 do @y @@ -327,20 +327,20 @@ if z>=@'1000000000 then abort('Character size is too large!'); while z>=@'40000000 do @z -@x [108] l.2060 Declare full_name. +@x [108] l.2061 Declare full_name. @!dvi_loc:int_32; {where we are about to look, in |dvi_file|} @y @!dvi_loc:int_32; {where we are about to look, in |dvi_file|} @!full_name: ^char; @z -@x [109] l.2067 Declare bad_dvi as noreturn +@x [109] l.2068 Declare bad_dvi as noreturn procedure bad_dvi; @y noreturn procedure bad_dvi; @z -@x [110] l.2076 Fix up opening the binary files +@x [110] l.2077 Fix up opening the binary files @ To prepare |dvi_file| for input, we |reset| it. @= @@ -353,7 +353,7 @@ dvi_loc:=0; dvi_loc:=0; @z -@x [112] l.2114 Make dvi_length() and dvi_move() work. +@x [112] l.2115 Make dvi_length() and dvi_move() work. @p function dvi_length:int_32; begin set_pos(dvi_file,-1); dvi_length:=cur_pos(dvi_file); end; @@ -374,13 +374,13 @@ dvi_loc:=n; end; @z -@x [135] l.2467 Lower case file name extensions. +@x [135] l.2468 Lower case file name extensions. id3(".")("V")("F")(vf_ext); {file name extension for \.{VF} files} @y id3(".")("v")("f")(vf_ext); {file name extension for \.{VF} files} @z -@x [137] l.2481 Set default directory name +@x [137] l.2482 Set default directory name @ If no font directory has been specified, \.{\title} is supposed to use the default \.{VF} directory, which is a system-dependent place where the \.{VF} files for standard fonts are kept. @@ -407,7 +407,7 @@ by setting the \.{VFFONTS} environment variable. @ (No initialization to be done. Keep this module to preserve numbering.) @z -@x [139] l.2498 Open VF file +@x [139] l.2499 Open VF file @= make_font_name(VF_default_area_name_length)(VF_default_area)(vf_ext); reset(vf_file,cur_name); @@ -426,7 +426,7 @@ if full_name then begin end else @z -@x [163] l.2937 copy elements of array piece by piece +@x [163] l.2938 copy elements of array piece by piece @ @= append_one(push); vf_move[vf_ptr]:=vf_move[vf_ptr-1]; @@ -444,19 +444,19 @@ append_one(push); vf_move_assign; @z -@x [170] l.3033 and again... +@x [170] l.3034 and again... vf_move[vf_ptr]:=vf_move[vf_ptr-1]; @y vf_move_assign; @z -@x [176] l.3138 break is fflush. +@x [176] l.3139 break is fflush. @d update_terminal == break(output) {empty the terminal output buffer} @y @d update_terminal == fflush(stdout) {empty the terminal output buffer} @z -@x [176] l.3148 +@x [176] l.3149 procedure input_ln; {inputs a line from the terminal} var k:0..terminal_line_length; begin if n_opt=0 then @@ -484,42 +484,42 @@ while (k= rewrite(out_file); {prepares to write packed bytes to |out_file|} @y @= @z -@x [248] l.4141 Use external routine to output bytes. +@x [248] l.4142 Use external routine to output bytes. @d out_byte(#) == write(out_file,#) {write next \.{DVI} byte} @y @d out_byte(#) == put_byte(#,out_file) {write next \.{DVI} byte} @z -@x [260] l.4259 String declaration. +@x [260] l.4260 String declaration. @!comment:packed array[1..comm_length] of char; {preamble comment prefix} @y @!comment:const_c_string; {preamble comment prefix} @z -@x [261] l.4270 Output the string from 0 to len-1, not 1 to len. +@x [261] l.4271 Output the string from 0 to len-1, not 1 to len. for k:=1 to comm_length do append_byte(xord[comment[k]]); @y for k:=0 to comm_length - 1 do append_byte(xord[ucharcast(comment[k])]); @z -@x [293] l.4480 System-dependent changes. +@x [293] l.4481 System-dependent changes. This section should be replaced, if necessary, by changes to the program that are necessary to make \.{DVIcopy} work at a particular installation. It is usually best to design your change file so that all changes to @@ -536,7 +536,7 @@ by the index variable |option_index|. @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) -@ = +@ = procedure parse_arguments; const n_options = 5; {Pascal won't count array lengths for us.} var @!long_options: array[0..n_options] of getopt_struct; diff --git a/source/texk/web2c/dvicopy.web b/source/texk/web2c/dvicopy.web index e24ad85b0..8220a18ff 100644 --- a/source/texk/web2c/dvicopy.web +++ b/source/texk/web2c/dvicopy.web @@ -22,6 +22,7 @@ % bug fix (not for Web2C) and some typos (May 2014) % from Udo Wermuth (u.wermuth@@icloud.com). % 17 July 2018, still version 1.6: typos corrected, no code changes. +% 02 Sep 2024, still version 1.6: fix sorting order of names-of-sections. % Here is TeX material that gets inserted after \input webmac \def\hang{\hangindent 3em\indent\ignorespaces} @@ -32,7 +33,7 @@ \def\MF{{\logo META}\-{\logo FONT}} \mathchardef\RA="3221 % right arrow -\def\(#1){} % this is used to make section names sort themselves better +\def\({} % this is used to make section names sort themselves better \def\9#1{} % this is used for sort keys in the index \def\title{DVI\lowercase{copy}} % don't change this line! @@ -1747,7 +1748,7 @@ begin new_line; case font_type(cur_fnt) of defined_font: confusion(str_fonts); loaded_font: bad_tfm; - @@;@/ + @@;@/ othercases abort('internal error'); endcases; end; @@ -2470,7 +2471,7 @@ id3(".")("V")("F")(vf_ext); {file name extension for \.{VF} files} gives an error message which refers the user to \.{VFtoVP} and \.{VPtoVF}, and terminates \.{\title}. -@= +@= vf_font_type: begin print('Bad VF file'); print_font(cur_fnt); @.Bad VF file@> print_ln(' loc=',vf_loc:1); @@ -3523,7 +3524,7 @@ routine determines whether a page shall be processed or skipped and sets the variable |type_setting| accordingly. @p procedure do_bop;@/ -@@; +@@; @!i,@!j:0..9; {indices into |count|} begin @; print('DVI: '); @@ -3642,7 +3643,7 @@ be updated (\\{set} commands). The |do_rule| procedure is called in order to typeset a rule. @p procedure do_rule;@/ -@@; +@@; @!visible:boolean; begin h_rule_pixels@; if (cur_h_dimen>0)and(cur_v_dimen>0) then @@ -3663,7 +3664,7 @@ character~|cur_res| with extension~|cur_ext| from the real font~|cur_fnt|. @p procedure do_char;@/ @@; -begin @@; +begin @@; if cur_upd then begin h_upd_char(widths[cur_wp])(char_pixels[cur_cp]); @@; @@ -4284,7 +4285,7 @@ for r:=p to q-1 do out_one(bo(byte_mem[r])); @ These are the additional local variables (if any) needed for |do_bop|; the variables |@!i| and |@!j| are already declared. -@= +@= var @ And here is the device dependent code for |do_bop|. @@ -4378,7 +4379,7 @@ out_four(width_dimen); out_four(cur_h_dimen); @ These are the additional local variables (if any) needed for |do_rule|; the variable |@!visible| is already declared. -@= +@= var @ And here is the device dependent code for |do_rule|. @@ -4421,7 +4422,7 @@ out_fnt_def(cur_fnt); @ And here is the device dependent code for |do_char|. -@= +@= @!debug if font_type(cur_fnt)<>out_font_type then confusion(str_fonts); gubed @; if cur_fnt<>out_fnt then diff --git a/source/texk/web2c/dvitype.ch b/source/texk/web2c/dvitype.ch index c22c080a6..d17904ff0 100644 --- a/source/texk/web2c/dvitype.ch +++ b/source/texk/web2c/dvitype.ch @@ -20,6 +20,12 @@ % 01/16/90 (SR) To version 3.2. % (more recent changes in the ChangeLog) +@x [0] l.29 +\def\(#1){} % this is used to make section names sort themselves better +@y +\def\({} % this is used to make section names sort themselves better +@z + @x [0] l.32 \def\title{DVI$\,$\lowercase{type}} @y @@ -55,7 +61,7 @@ procedure initialize; {this procedure gets things started properly} var i:integer; {loop index for initializations} begin print_ln(banner);@/ @y -@ +@ procedure initialize; {this procedure gets things started properly} var i:integer; {loop index for initializations} begin @@ -535,7 +541,7 @@ Parse a Unix-style command line. @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) -@ = +@ = procedure parse_arguments; const n_options = 8; {Pascal won't count array lengths for us.} var @!long_options: array[0..n_options] of getopt_struct; diff --git a/source/texk/web2c/gftodvi.ch b/source/texk/web2c/gftodvi.ch index 90ecd85da..5b895f02a 100644 --- a/source/texk/web2c/gftodvi.ch +++ b/source/texk/web2c/gftodvi.ch @@ -35,6 +35,12 @@ % Revision 0.3 84/11/17 23:51:56 richards % Base version for GFtoDVI Version 0.3 +@x [0] l.29 +\def\(#1){} % this is used to make section names sort themselves better +@y +\def\({} % this is used to make section names sort themselves better +@z + @x [0] l.32 \def\title{GF$\,$\lowercase{to}$\,$DVI} @y @@ -77,7 +83,7 @@ procedure initialize; {this procedure gets things started properly} const @@/ type @@/ var @@/ -@ +@ procedure initialize; {this procedure gets things started properly} var @!i,@!j,@!m,@!n:integer; {loop indices for initializations} begin @@ -612,7 +618,7 @@ Parse a Unix-style command line. @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) -@ = +@ = procedure parse_arguments; const n_options = 4; {Pascal won't count array lengths for us.} var @!long_options: array[0..n_options] of getopt_struct; diff --git a/source/texk/web2c/gftopk.ch b/source/texk/web2c/gftopk.ch index 62af338db..f892e4ba3 100644 --- a/source/texk/web2c/gftopk.ch +++ b/source/texk/web2c/gftopk.ch @@ -11,6 +11,12 @@ % on the origin of fonts in both gf and pk formats. The program runs % silently unless it is given the -v switch in the command line. +@x [0] l.41 +\def\(#1){} % this is used to make section names sort themselves better +@y +\def\({} % this is used to make section names sort themselves better +@z + @x [0] l.44 \def\title{GFtoPK} @y @@ -63,7 +69,7 @@ produced only when the \.{-v} command line flag is presented. const @@/ type @@/ var @@/ -@ +@ procedure initialize; {this procedure gets things started properly} var i:integer; {loop index for initializations} begin @@ -414,7 +420,7 @@ Parse a Unix-style command line. @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) @d do_nothing == {empty statement} -@ = +@ = procedure parse_arguments; const n_options = 3; {Pascal won't count array lengths for us.} var @!long_options: array[0..n_options] of getopt_struct; diff --git a/source/texk/web2c/gftype.ch b/source/texk/web2c/gftype.ch index 2e5155024..74bc8d4de 100644 --- a/source/texk/web2c/gftype.ch +++ b/source/texk/web2c/gftype.ch @@ -15,6 +15,12 @@ % turns on images. There is no terminal input to this program. % Output is to stdout, and may, of course, be redirected. +@x [0] l.27 +\def\(#1){} % this is used to make section names sort themselves better +@y +\def\({} % this is used to make section names sort themselves better +@z + @x [0] l.30 \def\title{GFtype} @y @@ -57,7 +63,7 @@ procedure initialize; {this procedure gets things started properly} const @@/ type @@/ var @@/ -@ +@ procedure initialize; {this procedure gets things started properly} var i:integer; {loop index for initializations} @!bound_default:integer; {temporary for setup} @@ -443,7 +449,7 @@ Parse a Unix-style command line. @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) @d do_nothing == {empty statement} -@ = +@ = procedure parse_arguments; const n_options = 4; {Pascal won't count array lengths for us.} var @!long_options: array[0..n_options] of getopt_struct; diff --git a/source/texk/web2c/mft.ch b/source/texk/web2c/mft.ch index 57f825791..4bb78a0bc 100644 --- a/source/texk/web2c/mft.ch +++ b/source/texk/web2c/mft.ch @@ -74,7 +74,7 @@ procedure initialize; var @@/ begin @@/ @y -@ +@ procedure initialize; var @@/ begin @@ -989,7 +989,7 @@ used to provide basic formatting. @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) -@ = +@ = procedure parse_arguments; const n_options = 5; {Pascal won't count array lengths for us.} var @!long_options: array[0..n_options] of getopt_struct; diff --git a/source/texk/web2c/patgen.ch b/source/texk/web2c/patgen.ch index e6accc88d..c4c45d12a 100644 --- a/source/texk/web2c/patgen.ch +++ b/source/texk/web2c/patgen.ch @@ -53,7 +53,7 @@ procedure initialize; {this procedure gets things started properly} var @@/ begin print_ln(banner);@/ @y -@ +@ procedure initialize; {this procedure gets things started properly} var @@/ begin @@ -97,11 +97,11 @@ error message about what caused the error. % machines, from Johannes Hielscher, 10 Jul 2019 00:00:03 (tex-live list), % and later from Mojca Miklavec, 23 Sep 2019 21:21:42. % It seems hopeless, so went back to the original values (10000000/500000). -% +% % The real solution is to provide a way to allocate the arrays % dynamically, so that the large arrays can be used by those who need % them but other are not affected. -% +% % If the values here are still too big, you can probably get it to work % by adding swap or zram; or write a patch to allocate the arrays dynamically. @x [27] @@ -243,7 +243,7 @@ Parse a Unix-style command line. @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) -@ = +@ = procedure parse_arguments; const n_options = 2; {Pascal won't count array lengths for us.} var @!long_options: array[0..n_options] of getopt_struct; diff --git a/source/texk/web2c/patgen.web b/source/texk/web2c/patgen.web index a34597237..1d6a7f40e 100644 --- a/source/texk/web2c/patgen.web +++ b/source/texk/web2c/patgen.web @@ -7,11 +7,14 @@ % Version 2.3 avoided division by zero - Karl Berry (October, 1996). % Version 2.4 avoided use of uninitialized variables (September, 2009). % A few typos fixed, no version change (April, 2020). +% Sorting order fixed, no version change (September, 2024). % Here is TeX material that gets inserted after \input webmac \def\hang{\hangindent 3em\indent\ignorespaces} \def\PASCAL{Pascal} +\def\({} % this is used to make section names sort themselves better + \def\title{PATGEN} \def\contentspagenumber{45} % should be odd \def\topofcontents{\null @@ -722,7 +725,7 @@ right of the occupied region (starting at |trie_max+1|). @p function first_fit: trie_pointer; label found, not_found; var s, @!t: trie_pointer; @!q: q_index; -begin @; for q:=1 to qmax do {pack it} begin t:=s+q_char(q);@/ @@ -743,7 +746,7 @@ one level of patterns is being generated, the threshold is set to 7 on subsequent levels because the pattern trie will be sparser after bad patterns are deleted (see |delete_bad_patterns|). -@= +@= if qmax>qmax_thresh then t:=trie_back(trie_max+1) @+else t:=0; loop begin t:=trie_link(t); s:=t-q_char(1); {get next unoccupied cell} @; @@ -914,7 +917,7 @@ end; @p function firstc_fit: triec_pointer; label found, not_found; var a, @!b: triec_pointer; @!q: q_index; -begin @; for q:=1 to qmax do {pack it} begin a:=b+q_char(q);@/ @@ -932,7 +935,7 @@ end; @ The threshold for attempting a first-fit packing is 3 transitions, which is lower than for the pattern trie because speed is more important here. -@= +@= if qmax>3 then a:=triec_back(triec_max+1) @+else a:=0; loop begin a:=triec_link(a); b:=a-q_char(1);@/ @; diff --git a/source/texk/web2c/pktogf.ch b/source/texk/web2c/pktogf.ch index 1dc768e46..7f6fc2d80 100644 --- a/source/texk/web2c/pktogf.ch +++ b/source/texk/web2c/pktogf.ch @@ -12,7 +12,7 @@ % gf and pk formats. PKtoGF runs silently unless it is given the % -v switch in the command line. -@x [0] l.21 +@x [0] l.22 \def\title{PKtoGF} @y \def\title{PK$\,$\lowercase{to}$\,$GF changes for C} @@ -60,7 +60,7 @@ procedure initialize; {this procedure gets things started properly} var i:integer; {loop index for initializations} begin print_ln(banner);@/ @y -@ +@ procedure initialize; {this procedure gets things started properly} var i:integer; {loop index for initializations} begin @@ -459,7 +459,7 @@ Parse a Unix-style command line. @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) -@ = +@ = procedure parse_arguments; const n_options = 3; {Pascal won't count array lengths for us.} var @!long_options: array[0..n_options] of getopt_struct; diff --git a/source/texk/web2c/pktogf.web b/source/texk/web2c/pktogf.web index eadd46c09..abe9a23fd 100644 --- a/source/texk/web2c/pktogf.web +++ b/source/texk/web2c/pktogf.web @@ -8,6 +8,7 @@ % Cleaned up description (bitweight errors) no version change: July 1990 % Fixed bug with empty character setting min_n to 1 (1.1): 19 October 1990 % A few typos, no version change: 22 April 2020, 27 October 2020 +% Sorting order fixed, no version change: 02 September 2024 \def\versiondate{22 April 2020} % \font\ninerm=cmr9 @@ -16,7 +17,7 @@ \def\MF{{\logo META}\-{\logo FONT}} \def\PASCAL{{\mc Pascal}} \def\tamu{Texas A\char38 M} -\def\(#1){} % this is used to make section names sort themselves better +\def\({} % this is used to make section names sort themselves better \def\9#1{} % this is used for sort keys in the index \def\title{PKtoGF} \def\contentspagenumber{1} @@ -1197,7 +1198,7 @@ else @ ; @ ; @ ; -@ ; +@ ; @ ; gf_byte(eoc) ; last_eoc := gf_loc ; @@ -1360,7 +1361,7 @@ for i := 0 to 255 do @ This module takes care of the simple job of writing the character preamble, after picking one to fit. -@= +@= begin if (char_pointer[car mod 256] = -1) and (car >= 0) and (car < 256) and @@ -1408,7 +1409,7 @@ end @ And another module to write out those character locators we have so carefully saved up the information for. -@= +@= for i := 0 to 255 do if char_pointer[i] <> -1 then begin if (s_ver_esc[i] = 0) and (s_hor_esc[i] >= 0) and @@ -1615,7 +1616,7 @@ gf_quad(mmin_m) ; gf_quad(mmax_m) ; gf_quad(mmin_n) ; gf_quad(mmax_n) ; -@ ; +@ ; gf_byte(post_post) ; gf_quad(j) ; gf_byte(gf_id_byte) ; diff --git a/source/texk/web2c/pktype.ch b/source/texk/web2c/pktype.ch index df785ce8b..583168439 100644 --- a/source/texk/web2c/pktype.ch +++ b/source/texk/web2c/pktype.ch @@ -8,6 +8,12 @@ % There is no terminal input to this program. % Output is to stdout, and may, of course, be redirected. +@x [0] l.25 +\def\(#1){} % this is used to make section names sort themselves better +@y +\def\({} % this is used to make section names sort themselves better +@z + @x [0] l.27 \def\title{PKtype} @y @@ -46,7 +52,7 @@ procedure initialize; {this procedure gets things started properly} @y type @@/ var @@/ -@ +@ procedure initialize; {this procedure gets things started properly} var i:integer; {loop index for initializations} begin @@ -335,7 +341,7 @@ Parse a Unix-style command line. @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) -@ = +@ = procedure parse_arguments; const n_options = 2; {Pascal won't count array lengths for us.} var @!long_options: array[0..n_options] of getopt_struct; diff --git a/source/texk/web2c/pltotf.ch b/source/texk/web2c/pltotf.ch index fcc08fbc5..c4a9a535d 100644 --- a/source/texk/web2c/pltotf.ch +++ b/source/texk/web2c/pltotf.ch @@ -11,6 +11,12 @@ % 01/16/90 (SR) Version 3.2. % (more recent changes in the ChangeLog) +@x [0] l.31 +\def\(#1){} % this is used to make section names sort themselves better +@y +\def\({} % this is used to make section names sort themselves better +@z + @x [0] l.34 \def\title{PL\lowercase{to}TF} @y @@ -45,7 +51,7 @@ procedure initialize; {this procedure gets things started properly} var @@/ begin print_ln(banner);@/ @y -@ +@ procedure initialize; {this procedure gets things started properly} var @@/ begin kpse_set_program_name (argv[0], my_name); @@ -263,7 +269,7 @@ Parse a Unix-style command line. @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) -@ = +@ = procedure parse_arguments; const n_options = 3; {Pascal won't count array lengths for us.} var @!long_options: array[0..n_options] of getopt_struct; diff --git a/source/texk/web2c/pooltype.ch b/source/texk/web2c/pooltype.ch index 74b4d9a23..8aa110642 100644 --- a/source/texk/web2c/pooltype.ch +++ b/source/texk/web2c/pooltype.ch @@ -4,6 +4,12 @@ % 11/29/89 (KB) Version released with 8-bit TeX. % (more recent changes in the ChangeLog) +@x [0] l.13 +\def\(#1){} % this is used to make section names sort themselves better +@y +\def\({} % this is used to make section names sort themselves better +@z + @x [0] l.16 \def\title{POOL\lowercase{type}} @y @@ -34,7 +40,7 @@ procedure initialize; {this procedure gets things started properly} var @@; begin @@/ @y -@ +@ procedure initialize; {this procedure gets things started properly} var @@; begin @@ -112,7 +118,7 @@ Parse a Unix-style command line. @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) -@ = +@ = procedure parse_arguments; const n_options = 2; {Pascal won't count array lengths for us.} var @!long_options: array[0..n_options] of getopt_struct; diff --git a/source/texk/web2c/ptexdir/ChangeLog b/source/texk/web2c/ptexdir/ChangeLog index 2fe03aef7..afa4807a6 100644 --- a/source/texk/web2c/ptexdir/ChangeLog +++ b/source/texk/web2c/ptexdir/ChangeLog @@ -1,3 +1,13 @@ +2024-09-16 TANAKA Takuji + + * ptex-base.ch: Use constants enc_jis and enc_ucs. + * ptex-{ctrlsym,prntknj,ucs}.test, + tests/{control-symbol,ctrlsym,endlinechar,printkanji,ucs}.tex, + tests/{ctrlsym,endline,jctrlsym,pknj-{e,s},ucs-{e,s}).log, + tests/p-{endline,jctrlsym,pknj-{e,s}}a.typ: + Add regression tests by using Kitagawa-san's sample files. + * am/ptex.am: Adjust. + 2024-05-18 Hironori Kitagawa * ptex-base.ch: Enable to get character codes diff --git a/source/texk/web2c/ptexdir/am/ptex.am b/source/texk/web2c/ptexdir/am/ptex.am index ee8117c68..ce807ade2 100644 --- a/source/texk/web2c/ptexdir/am/ptex.am +++ b/source/texk/web2c/ptexdir/am/ptex.am @@ -107,9 +107,14 @@ EXTRA_DIST += \ ptex_tests = \ ptexdir/ptriptest.test \ ptexdir/pver.test \ - ptexdir/wcfname.test + ptexdir/wcfname.test \ + ptexdir/ptex-ctrlsym.test \ + ptexdir/ptex-prntknj.test \ + ptexdir/ptex-ucs.test ptexdir/ptriptest.log: ptex$(EXEEXT) dvitype$(EXEEXT) pltotf$(EXEEXT) tftopl$(EXEEXT) -ptexdir/pver.log ptexdir/wcfname.log: ptex$(EXEEXT) +ptexdir/pver.log ptexdir/wcfname.log \ + ptexdir/ptex-ctrlsym.log ptexdir/ptex-prntknj.log \ + ptexdir/ptex-ucs.log: ptex$(EXEEXT) EXTRA_DIST += $(ptex_tests) $(pweb_tests) DISTCLEANFILES += $(pweb_programs:=.c) $(pweb_programs:=.h) \ @@ -166,12 +171,29 @@ EXTRA_DIST += ptexdir/tests/skipjfmp.pl ptexdir/tests/skipjfmp.tfm DISTCLEANFILES += ptests/xskipjfmp.* ## ptexdir/ptriptest EXTRA_DIST += ptexdir/ptrip/ptrip.diffs ptexdir/ptrip/texmf.cnf +DISTCLEANFILES += ptrip.diffs + +## ptex-ctrlsym.test +EXTRA_DIST += ptexdir/tests/ctrlsym.tex ptexdir/tests/ctrlsym.log \ + ptexdir/tests/endlinechar.tex ptexdir/tests/endline.log \ + ptexdir/tests/control-symbol.tex ptexdir/tests/jctrlsym.log \ + ptexdir/tests/p-endlinea.typ ptexdir/tests/p-jctrlsyma.typ +DISTCLEANFILES += p-ctrlsym.log p-ctrlsym.out p-ctrlsym.tex \ + p-endline*.* p-jctrlsym*.* +## ptexdir/ptex-prntknj.test +EXTRA_DIST += ptexdir/tests/printkanji.tex \ + ptexdir/tests/pknj-s.log ptexdir/tests/pknj-e.log \ + ptexdir/tests/p-pknj-sa.typ ptexdir/tests/p-pknj-ea.typ +DISTCLEANFILES += p-pknj-*.* +## ptex-ucs.test +EXTRA_DIST += ptexdir/tests/ucs.tex ptexdir/tests/ucs-s.log \ + ptexdir/tests/ucs-e.log +DISTCLEANFILES += p-ucs*.* + ptrip.diffs: ptex$(EXEEXT) dvitype$(EXEEXT) pltotf$(EXEEXT) tftopl$(EXEEXT) $(triptrap_diffs) $@ .PHONY: ptrip-clean ptrip-clean: rm -rf ptripdir -DISTCLEANFILES += ptrip.diffs - # (end of ptex.am) diff --git a/source/texk/web2c/ptexdir/ptex-base.ch b/source/texk/web2c/ptexdir/ptex-base.ch index 6b77387d5..528a7b7ae 100644 --- a/source/texk/web2c/ptexdir/ptex-base.ch +++ b/source/texk/web2c/ptexdir/ptex-base.ch @@ -1523,6 +1523,9 @@ primitive("ptextracingfonts",assign_int,int_base+ptex_tracing_fonts_code);@/ @d v_offset==dimen_par(v_offset_code) @d t_baseline_shift==dimen_par(t_baseline_shift_code) @d y_baseline_shift==dimen_par(y_baseline_shift_code) +@# +@d enc_jis=1 +@d enc_ucs=2 @z @x l.5542 - pTeX: @@ -1660,8 +1663,8 @@ procedure print_font_dir_and_enc(f:internal_font_number); begin if font_dir[f]=dir_tate then print("/TATE") else if font_dir[f]=dir_yoko then print("/YOKO"); - if font_enc[f]=2 then print("+Unicode") - else if font_enc[f]=1 then print("+JIS"); + if font_enc[f]=enc_ucs then print("+Unicode") + else if font_enc[f]=enc_jis then print("+JIS"); end; @z @@ -3324,9 +3327,9 @@ if jfm_flag<>dir_default then for k:=ctype_base[f] to ctype_base[f]+nt-1 do begin fget; read_twentyfourx(cx); - if jfm_enc=2 then {Unicode TFM} + if jfm_enc=enc_ucs then {Unicode TFM} font_info[k].hh.rh:=toDVI(fromUCS(cx)) - else if jfm_enc=1 then {JIS-encoded TFM} + else if jfm_enc=enc_jis then {JIS-encoded TFM} font_info[k].hh.rh:=toDVI(fromJIS(cx)) else font_info[k].hh.rh:=tokanji(cx); {|kchar_code|} @@ -3584,9 +3587,9 @@ continue: end; p:=link(p); jc:=KANJI(info(p)); - if font_enc[f]=2 then {Unicode TFM} + if font_enc[f]=enc_ucs then {Unicode TFM} jc:=toUCS(jc) - else if font_enc[f]=1 then {JIS-encoded TFM} + else if font_enc[f]=enc_jis then {JIS-encoded TFM} begin if toJIS(jc)=0 then char_warning_jis(f,jc); jc:=toJIS(jc); end else @@ -7075,8 +7078,8 @@ exit:end; @ @= begin jfm_enc:=0; if scan_keyword_noexpand("in") then - if scan_keyword_noexpand("jis") then jfm_enc:=1 - else if scan_keyword_noexpand("ucs") then jfm_enc:=2 + if scan_keyword_noexpand("jis") then jfm_enc:=enc_jis + else if scan_keyword_noexpand("ucs") then jfm_enc:=enc_ucs else begin print_err("Unknown TFM encoding"); @.Unknown TFM encoding@> diff --git a/source/texk/web2c/ptexdir/ptex-ctrlsym.test b/source/texk/web2c/ptexdir/ptex-ctrlsym.test new file mode 100755 index 000000000..0b84032af --- /dev/null +++ b/source/texk/web2c/ptexdir/ptex-ctrlsym.test @@ -0,0 +1,59 @@ +#! /bin/sh -vx +# Copyright 2024 Japanese TeX Development Community +# You may freely use, modify and/or distribute this file. + +BinDir=${BinDir:-.} +ExeExt=${ExeExt:-} +_ptex=$BinDir/ptex$ExeExt +_updvitype=$BinDir/updvitype$ExeExt + +LC_ALL=C; export LC_ALL; LANGUAGE=C; export LANGUAGE + +TEXMFCNF=$srcdir/../kpathsea;export TEXMFCNF +TEXINPUTS=".;$srcdir/tests"; export TEXINPUTS +TEXFONTS=".;$srcdir//tests"; export TEXFONTS +TEXFORMATS=.; export TEXFORMATS + +rm -f p-ctrlsym.tex p-endline*.* p-jctrlsym*.* + +if test ! -f ./p-basic.tex; then + cp $srcdir/tests/dump-basic.tex ./p-basic.tex +fi +if test ! -f ./p-basic-euc.fmt; then + $_ptex -ini -kanji-internal=euc -jobname=p-basic-euc p-basic || exit 2 +fi + +# ctrlsym.tex +$LN_S $srcdir/ptexdir/tests/ctrlsym.tex ./p-ctrlsym.tex +$_ptex -fmt=p-basic-euc p-ctrlsym || exit 2 + +sed 1d p-ctrlsym.log >p-ctrlsym.out + +diff $srcdir/ptexdir/tests/ctrlsym.log p-ctrlsym.out || exit 3 + + +# endlinchar.tex +$LN_S $srcdir/ptexdir/tests/endlinechar.tex ./p-endline.tex +$_ptex -fmt=p-basic-euc -interaction=batchmode p-endline.tex || : + +sed 1d p-endline.log >p-endline.out + +diff $srcdir/ptexdir/tests/endline.log p-endline.out || exit 4 + +$_updvitype ./p-endline.dvi >ptests/xp-endline.typ +sed "1d;s/TeX output 20[23].\...\...:.*'/TeX output 20XX.XX.XX'/" ptests/xp-endline.typ >ptests/xp-endlinea.typ +diff $srcdir/ptexdir/tests/p-endlinea.typ ptests/xp-endlinea.typ || exit 5 + + +# control-symbol.tex +$LN_S $srcdir/ptexdir/tests/control-symbol.tex ./p-jctrlsym.tex +$_ptex -fmt=p-basic-euc -interaction=batchmode p-jctrlsym.tex || : + +sed 1d p-jctrlsym.log >p-jctrlsym.out + +diff $srcdir/ptexdir/tests/jctrlsym.log p-jctrlsym.out || exit 6 + +$_updvitype ./p-jctrlsym.dvi >ptests/xp-jctrlsym.typ +sed "1d;s/TeX output 20[23].\...\...:.*'/TeX output 20XX.XX.XX'/" ptests/xp-jctrlsym.typ >ptests/xp-jctrlsyma.typ +diff $srcdir/ptexdir/tests/p-jctrlsyma.typ ptests/xp-jctrlsyma.typ || exit 7 + diff --git a/source/texk/web2c/ptexdir/ptex-prntknj.test b/source/texk/web2c/ptexdir/ptex-prntknj.test new file mode 100755 index 000000000..0f2c50f96 --- /dev/null +++ b/source/texk/web2c/ptexdir/ptex-prntknj.test @@ -0,0 +1,48 @@ +#! /bin/sh -vx +# Copyright 2024 Japanese TeX Development Community +# You may freely use, modify and/or distribute this file. + +BinDir=${BinDir:-.} +ExeExt=${ExeExt:-} +_ptex=$BinDir/ptex$ExeExt +_updvitype=$BinDir/updvitype$ExeExt + +LC_ALL=C; export LC_ALL; LANGUAGE=C; export LANGUAGE + +TEXMFCNF=$srcdir/../kpathsea;export TEXMFCNF +OFMFONTS=".;$srcdir/tests"; export OFMFONTS +TFMFONTS=".;$srcdir//tests"; export TFMFONTS +TEXINPUTS=".;$srcdir/tests"; export TEXINPUTS +TEXFORMATS=.; export TEXFORMATS + +rm -f p-base.* p-ucs*.* +$LN_S $srcdir/ptexdir/tests/printkanji.tex ./printkanji.tex + +if test ! -f ./p-basic.tex; then + cp $srcdir/tests/dump-basic.tex ./p-basic.tex +fi +if test ! -f ./p-basic-sjis.fmt; then + $_ptex -ini -kanji-internal=sjis -jobname=p-basic-sjis p-basic || exit 1 +fi +if test ! -f ./p-basic-euc.fmt; then + $_ptex -ini -kanji-internal=euc -jobname=p-basic-euc p-basic || exit 2 +fi + +$_ptex -fmt=p-basic-sjis -kanji-internal=sjis -jobname=p-pknj-s -interaction=batchmode printkanji || : +$_ptex -fmt=p-basic-euc -kanji-internal=euc -jobname=p-pknj-e -interaction=batchmode printkanji || : + +sed 1d p-pknj-s.log >p-pknj-s.out +sed 1d p-pknj-e.log >p-pknj-e.out + +diff $srcdir/ptexdir/tests/pknj-s.log p-pknj-s.out || exit 10 +diff $srcdir/ptexdir/tests/pknj-e.log p-pknj-e.out || exit 11 + +$_updvitype ./p-pknj-s.dvi >ptests/xp-pknj-s.typ +$_updvitype ./p-pknj-e.dvi >ptests/xp-pknj-e.typ + +sed "1d;s/TeX output 20[23].\...\...:.*'/TeX output 20XX.XX.XX'/" ptests/xp-pknj-s.typ >ptests/xp-pknj-sa.typ +sed "1d;s/TeX output 20[23].\...\...:.*'/TeX output 20XX.XX.XX'/" ptests/xp-pknj-e.typ >ptests/xp-pknj-ea.typ + +diff $srcdir/ptexdir/tests/p-pknj-sa.typ ptests/xp-pknj-sa.typ || exit 20 +diff $srcdir/ptexdir/tests/p-pknj-ea.typ ptests/xp-pknj-ea.typ || exit 21 + diff --git a/source/texk/web2c/ptexdir/ptex-ucs.test b/source/texk/web2c/ptexdir/ptex-ucs.test new file mode 100755 index 000000000..bef8ba449 --- /dev/null +++ b/source/texk/web2c/ptexdir/ptex-ucs.test @@ -0,0 +1,37 @@ +#! /bin/sh -vx +# Copyright 2024 Japanese TeX Development Community +# You may freely use, modify and/or distribute this file. + +BinDir=${BinDir:-.} +ExeExt=${ExeExt:-} +_ptex=$BinDir/ptex$ExeExt + +LC_ALL=C; export LC_ALL; LANGUAGE=C; export LANGUAGE + +TEXMFCNF=$srcdir/../kpathsea;export TEXMFCNF +OFMFONTS=".;$srcdir/tests"; export OFMFONTS +TEXINPUTS=".;$srcdir/tests"; export TEXINPUTS +TEXFORMATS=.; export TEXFORMATS + +rm -f p-ucs*.* +$LN_S $srcdir/ptexdir/tests/ucs.tex ./p-ucs.tex + +if test ! -f ./p-basic.tex; then + cp $srcdir/tests/dump-basic.tex ./p-basic.tex +fi +if test ! -f ./p-basic-sjis.fmt; then + $_ptex -ini -kanji-internal=sjis -jobname=p-basic-sjis p-basic || exit 1 +fi +if test ! -f ./p-basic-euc.fmt; then + $_ptex -ini -kanji-internal=euc -jobname=p-basic-euc p-basic || exit 2 +fi + +$_ptex -fmt=p-basic-sjis -kanji-internal=sjis -jobname=p-ucs-s -interaction=batchmode p-ucs || exit 4 +$_ptex -fmt=p-basic-euc -kanji-internal=euc -jobname=p-ucs-e -interaction=batchmode p-ucs || exit 5 + +sed 1d p-ucs-s.log >p-ucs-s.out +sed 1d p-ucs-e.log >p-ucs-e.out + +diff $srcdir/ptexdir/tests/ucs-s.log p-ucs-s.out || exit 10 +diff $srcdir/ptexdir/tests/ucs-e.log p-ucs-e.out || exit 11 + diff --git a/source/texk/web2c/ptexdir/tests/control-symbol.tex b/source/texk/web2c/ptexdir/tests/control-symbol.tex index f81275468..be0590660 100644 --- a/source/texk/web2c/ptexdir/tests/control-symbol.tex +++ b/source/texk/web2c/ptexdir/tests/control-symbol.tex @@ -1,5 +1,14 @@ \scrollmode % plain TeX ソース +\font\cmr=cmr10\cmr +\ifx\kanjiskip\undefined\else + \ifnum\jis"2121="3000 + \jfont\jpy=umin10 at 10pt\jpy + \else + \jfont\jpy=min10 at 10pt\jpy + \fi +\fi + \def\+{A} \def\+{A} \def\X{\+} @@ -95,7 +104,5 @@ 4. \】 ◇, \@ ◇ - \end - diff --git a/source/texk/web2c/ptexdir/tests/ctrlsym.log b/source/texk/web2c/ptexdir/tests/ctrlsym.log new file mode 100644 index 000000000..a74fd6faa --- /dev/null +++ b/source/texk/web2c/ptexdir/tests/ctrlsym.log @@ -0,0 +1,11 @@ + restricted \write18 enabled. + %&-line parsing enabled. +**p-ctrlsym +(./p-ctrlsym.tex +A: 49379 + +\雪 ->snow +B: 49379. 雪\雪snow +macro:->snow. + ) +No pages of output. diff --git a/source/texk/web2c/ptexdir/tests/ctrlsym.tex b/source/texk/web2c/ptexdir/tests/ctrlsym.tex new file mode 100644 index 000000000..d84a54170 --- /dev/null +++ b/source/texk/web2c/ptexdir/tests/ctrlsym.tex @@ -0,0 +1,36 @@ +% Copyright 2024 Japanese TeX Development Community +% You may freely use, modify and/or distribute this file. +% +\ifx\fmtname\undefined + \input basic + \def\fmtname{basic} + \expandafter\dump +\fi +%================== +\begingroup % Just there to minimize tracing output + \tracingmacros=2 + \tracingonline=1 +%-- + \newlinechar=10 + \count255=0 + \count255=`雪 \relax + \message{^^JA: \the\count255^^J} + \def\雪{snow} + \count255=`\雪 \relax + \message{B: \the\count255. 雪\string\雪 \雪^^J} + \message{\expandafter\meaning\csname 雪\endcsname.^^J} + \ifx\Uchar\undefined\else\message{\expandafter\meaning\csname \Uchar"96EA\endcsname.^^J}\fi% + \ifnum\jis"2121="3000 + \count4095=0 + \count4095=`🍌 \relax + \message{^^JC: \the\count4095^^J} + \def\🍌{banana} + \count4095=`\🍌 \relax + \message{D: \the\count4095. 🍌\string\🍌 \🍌^^J} + \message{\expandafter\meaning\csname 🍌\endcsname.^^J} + \ifx\Uchar\undefined\else\message{\expandafter\meaning\csname \Uchar"1F34C\endcsname.^^J}\fi% + \fi +%-- + \setbox0=\vbox{} % no dvi/xdv/pdf output +\endgroup +\end diff --git a/source/texk/web2c/ptexdir/tests/endline.log b/source/texk/web2c/ptexdir/tests/endline.log new file mode 100644 index 000000000..517be160e --- /dev/null +++ b/source/texk/web2c/ptexdir/tests/endline.log @@ -0,0 +1,24 @@ + restricted \write18 enabled. + %&-line parsing enabled. +**p-endline.tex +(./p-endline.tex +! Undefined control sequence. +l.29 7a\^^e3 + ^^81^^82b\^^e3^^81^^82 +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +l.29 7a\^^e3^^81^^82b\^^e3 + ^^81^^82 +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +[1] ) +Output written on p-endline.dvi (1 page, 232 bytes). diff --git a/source/texk/web2c/ptexdir/tests/endlinechar.tex b/source/texk/web2c/ptexdir/tests/endlinechar.tex index ef59b1fc8..5dc8de812 100644 --- a/source/texk/web2c/ptexdir/tests/endlinechar.tex +++ b/source/texk/web2c/ptexdir/tests/endlinechar.tex @@ -1,23 +1,23 @@ -\font\x=ecrm1000 \x +\font\x=ec-lmr10 \x \parindent0pt\noautoxspacing \output{\shipout\box255} -\def\あ{ア} -\def\,{イ} +\def\あ{PPP} +\def\,{QQQ} 1a\, -% --> 1aイ +% --> 1aQQQ 2a\あ -% --> 2aア +% --> 2aPPP \endlinechar=-1\relax 3a\, -% --> 3aイ +% --> 3aQQQ % previous pTeX, upTeX: Undefined cs. 4a\あ -% --> 4aア +% --> 4aPPP % prev. pTeX: Undefined cs. 5a, @@ -36,18 +36,22 @@ \catcode"81=11\relax \catcode"82=11\relax 8a\^^e3^^81^^82 - % --> 8aア + % (p3.10.0-u1.27) --> 8aPPP + % (p4.0.0-u1.27) --> エラー 8a \kcatcode`あ=15\relax 9a\あ - % == 9a\^^e3^^81^^82. --> 9aア - \def\^^e3^^81^^82{ウ} + % == 9a\^^e3^^81^^82. + % (p3.10.0-u1.27) --> 9aPPP + % (p4.0.0-u1.27) --> エラー 9a + \def\^^e3^^81^^82{RRR} 10a\あ b\あ - % == 10a\^^e3^^81^^82 b\^^e3^^81^^82. --> 10aウbウ + % == 10a\^^e3^^81^^82 b\^^e3^^81^^82. --> 10aRRRbRRR \kcatcode12354=16\relax 11a\あ b\あ - % == 10a\^^e3^^81^^82 b\^^e3^^81^^82. --> 11aウbウ + % == 11a\^^e3^^81^^82 b\^^e3^^81^^82. + % (p3.10.0-u1.27) --> 11aRRRbRRR + % (p4.0.0-u1.27) --> 11aPPPbPPP \fi \bye - diff --git a/source/texk/web2c/ptexdir/tests/jctrlsym.log b/source/texk/web2c/ptexdir/tests/jctrlsym.log new file mode 100644 index 000000000..a1e190a80 --- /dev/null +++ b/source/texk/web2c/ptexdir/tests/jctrlsym.log @@ -0,0 +1,42 @@ + restricted \write18 enabled. + %&-line parsing enabled. +**p-jctrlsym.tex +(./p-jctrlsym.tex +■control symbol +> \X=macro: +->\+. +l.27 \show\X + \relax\message{(\meaning\X)} + +(macro:->\+) +> \Y=macro: +->\+. +l.28 \show\Y + \relax\message{(\meaning\Y)} + +(macro:->\+) ■control word +> \X=macro: +->\+ . +l.39 \show\X + \relax\message{(\meaning\X)} + +(macro:->\+ ) +> \Y=macro: +->\+ . +l.40 \show\Y + \relax\message{(\meaning\Y)} + +(macro:->\+ ) ■control word +> \X=macro: +->\ABC . +l.48 \show\X + \relax\message{(\meaning\X)} + +(macro:->\ABC ) +> \Y=macro: +->\あいう . +l.49 \show\Y + \relax\message{(\meaning\Y)} + +(macro:->\あいう ) ■行末の和文コントロールシンボル [1] ) +Output written on p-jctrlsym.dvi (1 page, 376 bytes). diff --git a/source/texk/web2c/ptexdir/tests/p-endlinea.typ b/source/texk/web2c/ptexdir/tests/p-endlinea.typ new file mode 100644 index 000000000..31b9af3a8 --- /dev/null +++ b/source/texk/web2c/ptexdir/tests/p-endlinea.typ @@ -0,0 +1,68 @@ +Options selected: + Starting page = * + Maximum number of pages = 1000000 + Output level = 4 (the works) + Resolution = 300.00000000 pixels per inch +numerator/denominator=25400000/473628672 +magnification=1000; 0.00006334 pixels per DVI unit +' TeX output 20XX.XX.XX' +Postamble starts at byte 167. +maxv=42152922, maxh=30785863, maxstackdepth=1, totalpages=1 +Font 0: ec-lmr10---loaded at size 655360 DVI units + +42: beginning of page 1 +87: down3 655360 v:=0+655360=655360, vv:=42 +91: push +level 0:(h=0,v=655360,w=0,x=0,y=0,z=0,hh=0,vv=42) +92: fntdef1 0: ec-lmr10 +116: fntnum0 current font is ec-lmr10 +117: setchar49 ("31) h:=0+327680=327680, hh:=21 +118: setchar97 ("61) h:=327680+327680=655360, hh:=42 +119: setchar81 ("51) h:=655360+509738=1165098, hh:=74 +120: setchar81 ("51) h:=1165098+509738=1674836, hh:=106 +121: setchar81 ("51) h:=1674836+509738=2184574, hh:=138 +[1aQQQ] +122: pop +level 0:(h=0,v=655360,w=0,x=0,y=0,z=0,hh=0,vv=42) +123: y3 786432 v:=655360+786432=1441792, vv:=91 +127: push +level 0:(h=0,v=1441792,w=0,x=0,y=786432,z=0,hh=0,vv=91) +128: setchar50 ("32) h:=0+327680=327680, hh:=21 +129: setchar97 ("61) h:=327680+327680=655360, hh:=42 +130: setchar80 ("50) h:=655360+446005=1101365, hh:=70 +131: setchar80 ("50) h:=1101365+446005=1547370, hh:=98 +132: setchar80 ("50) h:=1547370+446005=1993375, hh:=126 +[2aPPP] +133: pop +level 0:(h=0,v=1441792,w=0,x=0,y=786432,z=0,hh=0,vv=91) +134: y0 786432 v:=1441792+786432=2228224, vv:=141 +135: push +level 0:(h=0,v=2228224,w=0,x=0,y=786432,z=0,hh=0,vv=141) +136: setchar51 ("33) h:=0+327680=327680, hh:=21 +137: setchar97 ("61) h:=327680+327680=655360, hh:=42 +138: setchar81 ("51) h:=655360+509738=1165098, hh:=74 +139: setchar81 ("51) h:=1165098+509738=1674836, hh:=106 +140: setchar81 ("51) h:=1674836+509738=2184574, hh:=138 +141: setchar52 ("34) h:=2184574+327680=2512254, hh:=159 +142: setchar97 ("61) h:=2512254+327680=2839934, hh:=180 +143: setchar80 ("50) h:=2839934+446005=3285939, hh:=208 +144: setchar80 ("50) h:=3285939+446005=3731944, hh:=236 +145: setchar80 ("50) h:=3731944+446005=4177949, hh:=264 +146: setchar53 ("35) h:=4177949+327680=4505629, hh:=285 +147: setchar97 ("61) h:=4505629+327680=4833309, hh:=306 +148: setchar54 ("36) h:=4833309+327680=5160989, hh:=327 +149: setchar97 ("61) h:=5160989+327680=5488669, hh:=348 +150: setchar55 ("37) h:=5488669+327680=5816349, hh:=369 +151: setchar97 ("61) h:=5816349+327680=6144029, hh:=390 +[3aQQQ4aPPP5a6a7a] +152: set1 129("81) h:=6144029+491520=6635549, hh:=421 +154: w2 -18205 h:=6635549-18205=6617344, hh:=420 +157: set1 130("82) h:=6617344+473301=7090645, hh:=450 +159: setchar98 ("62) h:=7090645+364085=7454730, hh:=473 +[b] +160: set1 129("81) h:=7454730+491520=7946250, hh:=504 +162: w0 -18205 h:=7946250-18205=7928045, hh:=503 +163: set1 130("82) h:=7928045+473301=8401346, hh:=533 +165: pop +level 0:(h=0,v=2228224,w=0,x=0,y=786432,z=0,hh=0,vv=141) +166: eop diff --git a/source/texk/web2c/ptexdir/tests/p-jctrlsyma.typ b/source/texk/web2c/ptexdir/tests/p-jctrlsyma.typ new file mode 100644 index 000000000..7f8a5eb1c --- /dev/null +++ b/source/texk/web2c/ptexdir/tests/p-jctrlsyma.typ @@ -0,0 +1,123 @@ +Options selected: + Starting page = * + Maximum number of pages = 1000000 + Output level = 4 (the works) + Resolution = 300.00000000 pixels per inch +numerator/denominator=25400000/473628672 +magnification=1000; 0.00006334 pixels per DVI unit +' TeX output 20XX.XX.XX' +Postamble starts at byte 293. +maxv=43725786, maxh=30785863, maxstackdepth=2, totalpages=1 +Font 1: min10 (JFM)---loaded at size 655360 DVI units +Font 0: cmr10---loaded at size 655360 DVI units + +42: beginning of page 1 +87: push +level 0:(h=0,v=0,w=0,x=0,y=0,z=0,hh=0,vv=0) +88: down3 -917504 v:=0-917504=-917504, vv:=-58 +92: pop +level 0:(h=0,v=0,w=0,x=0,y=0,z=0,hh=0,vv=0) +93: down4 42152922 v:=0+42152922=42152922, vv:=2670 +98: push +level 0:(h=0,v=42152922,w=0,x=0,y=0,z=0,hh=0,vv=2670) +99: down4 -41497562 v:=42152922-41497562=655360, vv:=42 +104: push +level 1:(h=0,v=655360,w=0,x=0,y=0,z=0,hh=0,vv=42) +105: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +109: fntdef1 0: cmr10 +130: fntnum0 current font is cmr10 +131: setchar49 ("31) h:=1310720+327681=1638401, hh:=104 +132: setchar46 ("2E) h:=1638401+182045=1820446, hh:=116 +133: right3 291271 h:=1820446+291271=2111717, hh:=134 +[1. ] +137: fntdef1 1: min10 +158: fntnum1 current font is min10 +159: set2 8737("2221) type=0 h:=2111717+630598=2742315, hh:=174 +162: set2 8574("217E) type=0 h:=2742315+630598=3372913, hh:=214 +165: set2 8484("2124) type=8 h:=3372913+231778=3604691, hh:=229 +168: right3 398820 h:=3604691+398820=4003511, hh:=254 +172: set2 8737("2221) type=0 h:=4003511+630598=4634109, hh:=294 +175: set2 8574("217E) type=0 h:=4634109+630598=5264707, hh:=334 +[∡ⅾℤ ∡ⅾ] +178: pop +level 1:(h=0,v=655360,w=0,x=0,y=0,z=0,hh=0,vv=42) +179: y3 786432 v:=655360+786432=1441792, vv:=91 +183: push +level 1:(h=0,v=1441792,w=0,x=0,y=786432,z=0,hh=0,vv=91) +184: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +188: fntnum0 current font is cmr10 +189: setchar50 ("32) h:=1310720+327681=1638401, hh:=104 +190: setchar46 ("2E) h:=1638401+182045=1820446, hh:=116 +191: right3 291271 h:=1820446+291271=2111717, hh:=134 +[2. ] +195: fntnum1 current font is min10 +196: set2 8737("2221) type=0 h:=2111717+630598=2742315, hh:=174 +199: set2 8574("217E) type=0 h:=2742315+630598=3372913, hh:=214 +[∡ⅾ] +202: fntnum0 current font is cmr10 +203: setchar44 ("2C) h:=3372913+182045=3554958, hh:=226 +204: right3 218453 h:=3554958+218453=3773411, hh:=239 +[, ] +208: fntnum1 current font is min10 +209: set2 8737("2221) type=0 h:=3773411+630598=4404009, hh:=279 +212: set2 8574("217E) type=0 h:=4404009+630598=5034607, hh:=319 +[∡ⅾ] +215: pop +level 1:(h=0,v=1441792,w=0,x=0,y=786432,z=0,hh=0,vv=91) +216: y0 786432 v:=1441792+786432=2228224, vv:=141 +217: push +level 1:(h=0,v=2228224,w=0,x=0,y=786432,z=0,hh=0,vv=141) +218: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +222: fntnum0 current font is cmr10 +223: setchar51 ("33) h:=1310720+327681=1638401, hh:=104 +224: setchar46 ("2E) h:=1638401+182045=1820446, hh:=116 +225: right3 291271 h:=1820446+291271=2111717, hh:=134 +[3. ] +229: fntnum1 current font is min10 +230: set2 8737("2221) type=0 h:=2111717+630598=2742315, hh:=174 +233: set2 8574("217E) type=0 h:=2742315+630598=3372913, hh:=214 +[∡ⅾ] +236: fntnum0 current font is cmr10 +237: setchar44 ("2C) h:=3372913+182045=3554958, hh:=226 +238: w3 218453 h:=3554958+218453=3773411, hh:=239 +[, ] +242: fntnum1 current font is min10 +243: set2 8737("2221) type=0 h:=3773411+630598=4404009, hh:=279 +246: w0 218453 h:=4404009+218453=4622462, hh:=293 +247: set2 8574("217E) type=0 h:=4622462+630598=5253060, hh:=333 +[∡ ⅾ] +250: pop +level 1:(h=0,v=2228224,w=0,x=0,y=786432,z=0,hh=0,vv=141) +251: y0 786432 v:=2228224+786432=3014656, vv:=191 +252: push +level 1:(h=0,v=3014656,w=0,x=0,y=786432,z=0,hh=0,vv=191) +253: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +257: fntnum0 current font is cmr10 +258: setchar52 ("34) h:=1310720+327681=1638401, hh:=104 +259: setchar46 ("2E) h:=1638401+182045=1820446, hh:=116 +260: right3 291271 h:=1820446+291271=2111717, hh:=134 +[4. ] +264: fntnum1 current font is min10 +265: set2 8737("2221) type=0 h:=2111717+630598=2742315, hh:=174 +268: w3 218453 h:=2742315+218453=2960768, hh:=188 +272: set2 8574("217E) type=0 h:=2960768+630598=3591366, hh:=228 +[∡ ⅾ] +275: fntnum0 current font is cmr10 +276: setchar44 ("2C) h:=3591366+182045=3773411, hh:=240 +277: w0 218453 h:=3773411+218453=3991864, hh:=253 +[, ] +278: fntnum1 current font is min10 +279: set2 8737("2221) type=0 h:=3991864+630598=4622462, hh:=293 +282: w0 218453 h:=4622462+218453=4840915, hh:=307 +283: set2 8574("217E) type=0 h:=4840915+630598=5471513, hh:=347 +[∡ ⅾ] +286: pop +level 1:(h=0,v=3014656,w=0,x=0,y=786432,z=0,hh=0,vv=191) +287: pop +level 0:(h=0,v=42152922,w=0,x=0,y=0,z=0,hh=0,vv=2670) +288: down3 1572864 v:=42152922+1572864=43725786, vv:=2770 +292: eop diff --git a/source/texk/web2c/ptexdir/tests/p-pknj-ea.typ b/source/texk/web2c/ptexdir/tests/p-pknj-ea.typ new file mode 100644 index 000000000..cf8d08f77 --- /dev/null +++ b/source/texk/web2c/ptexdir/tests/p-pknj-ea.typ @@ -0,0 +1,825 @@ +Options selected: + Starting page = * + Maximum number of pages = 1000000 + Output level = 4 (the works) + Resolution = 300.00000000 pixels per inch +numerator/denominator=25400000/473628672 +magnification=1000; 0.00006334 pixels per DVI unit +' TeX output 20XX.XX.XX' +Postamble starts at byte 1055. +maxv=43725786, maxh=30785863, maxstackdepth=3, totalpages=1 +Font 1: min10 (JFM)---loaded at size 655360 DVI units +Font 0: ec-lmr10---loaded at size 655360 DVI units + +42: beginning of page 50623 +87: push +level 0:(h=0,v=0,w=0,x=0,y=0,z=0,hh=0,vv=0) +88: down3 -917504 v:=0-917504=-917504, vv:=-58 +92: pop +level 0:(h=0,v=0,w=0,x=0,y=0,z=0,hh=0,vv=0) +93: down4 42152922 v:=0+42152922=42152922, vv:=2670 +98: push +level 0:(h=0,v=42152922,w=0,x=0,y=0,z=0,hh=0,vv=2670) +99: down4 -41497562 v:=42152922-41497562=655360, vv:=42 +104: push +level 1:(h=0,v=655360,w=0,x=0,y=0,z=0,hh=0,vv=42) +105: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +109: fntdef1 0: ec-lmr10 +133: fntnum0 current font is ec-lmr10 +134: setchar65 ("41) h:=1310720+491520=1802240, hh:=114 +135: setchar58 ("3A) h:=1802240+182043=1984283, hh:=126 +136: w3 218453 h:=1984283+218453=2202736, hh:=140 +[A: ] +140: set1 197("C5) h:=2202736+491520=2694256, hh:=171 +142: set1 191("BF) h:=2694256+491520=3185776, hh:=202 +144: w0 218453 h:=3185776+218453=3404229, hh:=216 +[ ] +145: set1 197("C5) h:=3404229+491520=3895749, hh:=247 +147: set1 191("BF) h:=3895749+491520=4387269, hh:=278 +149: w0 218453 h:=4387269+218453=4605722, hh:=292 +[ ] +150: fntdef1 1: min10 +171: fntnum1 current font is min10 +172: set2 17727("453F) type=0 h:=4605722+630598=5236320, hh:=332 +[䔿] +175: pop +level 1:(h=0,v=655360,w=0,x=0,y=0,z=0,hh=0,vv=42) +176: y3 786432 v:=655360+786432=1441792, vv:=91 +180: push +level 1:(h=0,v=1441792,w=0,x=0,y=786432,z=0,hh=0,vv=91) +181: push +level 2:(h=0,v=1441792,w=0,x=0,y=786432,z=0,hh=0,vv=91) +182: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +185: pop +level 2:(h=0,v=1441792,w=0,x=0,y=786432,z=0,hh=0,vv=91) +186: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +190: fntnum0 current font is ec-lmr10 +191: setchar92 ("5C) h:=630598+327680=958278, hh:=61 +192: setchar109 ("6D) h:=958278+546111=1504389, hh:=96 +193: setchar101 ("65) h:=1504389+291275=1795664, hh:=114 +194: setchar97 ("61) h:=1795664+327680=2123344, hh:=135 +195: setchar110 ("6E) h:=2123344+364085=2487429, hh:=158 +196: setchar105 ("69) h:=2487429+182043=2669472, hh:=170 +197: setchar110 ("6E) h:=2669472+364085=3033557, hh:=193 +198: setchar103 ("67) h:=3033557+327680=3361237, hh:=214 +199: setchar46 ("2E) h:=3361237+182043=3543280, hh:=226 +[\meaning.] +200: pop +level 1:(h=0,v=1441792,w=0,x=0,y=786432,z=0,hh=0,vv=91) +201: y0 786432 v:=1441792+786432=2228224, vv:=141 +202: push +level 1:(h=0,v=2228224,w=0,x=0,y=786432,z=0,hh=0,vv=141) +203: right3 1310720 h:=0+1310720=1310720, hh:=83 +207: setchar109 ("6D) h:=1310720+546111=1856831, hh:=118 +208: setchar97 ("61) h:=1856831+327680=2184511, hh:=139 +209: setchar99 ("63) h:=2184511+291275=2475786, hh:=157 +210: setchar114 ("72) h:=2475786+256683=2732469, hh:=173 +211: setchar111 ("6F) h:=2732469+327680=3060149, hh:=194 +212: setchar58 ("3A) h:=3060149+182043=3242192, hh:=206 +213: setchar45 ("2D) h:=3242192+218453=3460645, hh:=220 +214: setchar62 ("3E) h:=3460645+509738=3970383, hh:=252 +215: setchar109 ("6D) h:=3970383+546111=4516494, hh:=287 +216: setchar97 ("61) h:=4516494+327680=4844174, hh:=308 +217: setchar99 ("63) h:=4844174+291275=5135449, hh:=326 +218: setchar114 ("72) h:=5135449+256683=5392132, hh:=342 +219: setchar111 ("6F) h:=5392132+327680=5719812, hh:=363 +220: setchar58 ("3A) h:=5719812+182043=5901855, hh:=375 +221: setchar45 ("2D) h:=5901855+218453=6120308, hh:=389 +222: setchar62 ("3E) h:=6120308+509738=6630046, hh:=421 +[ macro:->macro:->] +223: set1 197("C5) h:=6630046+491520=7121566, hh:=452 +225: set1 191("BF) h:=7121566+491520=7613086, hh:=483 +227: w3 218453 h:=7613086+218453=7831539, hh:=496 +[ ] +231: set1 197("C5) h:=7831539+491520=8323059, hh:=527 +233: set1 191("BF) h:=8323059+491520=8814579, hh:=558 +235: w0 218453 h:=8814579+218453=9033032, hh:=572 +[ ] +236: fntnum1 current font is min10 +237: set2 17727("453F) type=0 h:=9033032+630598=9663630, hh:=612 +[䔿] +240: pop +level 1:(h=0,v=2228224,w=0,x=0,y=786432,z=0,hh=0,vv=141) +241: y0 786432 v:=2228224+786432=3014656, vv:=191 +242: push +level 1:(h=0,v=3014656,w=0,x=0,y=786432,z=0,hh=0,vv=191) +243: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +247: fntnum0 current font is ec-lmr10 +248: setchar109 ("6D) h:=1310720+546111=1856831, hh:=118 +249: setchar97 ("61) h:=1856831+327680=2184511, hh:=139 +250: setchar99 ("63) h:=2184511+291275=2475786, hh:=157 +251: setchar114 ("72) h:=2475786+256683=2732469, hh:=173 +252: setchar111 ("6F) h:=2732469+327680=3060149, hh:=194 +253: setchar58 ("3A) h:=3060149+182043=3242192, hh:=206 +254: setchar45 ("2D) h:=3242192+218453=3460645, hh:=220 +255: setchar62 ("3E) h:=3460645+509738=3970383, hh:=252 +[macro:->] +256: set1 197("C5) h:=3970383+491520=4461903, hh:=283 +258: set1 191("BF) h:=4461903+491520=4953423, hh:=314 +260: w3 218453 h:=4953423+218453=5171876, hh:=328 +[ ] +264: set1 197("C5) h:=5171876+491520=5663396, hh:=359 +266: set1 191("BF) h:=5663396+491520=6154916, hh:=390 +268: w0 218453 h:=6154916+218453=6373369, hh:=404 +[ ] +269: fntnum1 current font is min10 +270: set2 17727("453F) type=0 h:=6373369+630598=7003967, hh:=444 +[䔿] +273: pop +level 1:(h=0,v=3014656,w=0,x=0,y=786432,z=0,hh=0,vv=191) +274: y0 786432 v:=3014656+786432=3801088, vv:=241 +275: push +level 1:(h=0,v=3801088,w=0,x=0,y=786432,z=0,hh=0,vv=241) +276: push +level 2:(h=0,v=3801088,w=0,x=0,y=786432,z=0,hh=0,vv=241) +277: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +280: pop +level 2:(h=0,v=3801088,w=0,x=0,y=786432,z=0,hh=0,vv=241) +281: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +285: fntnum0 current font is ec-lmr10 +286: setchar92 ("5C) h:=630598+327680=958278, hh:=61 +287: setchar106 ("6A) h:=958278+200245=1158523, hh:=74 +288: setchar111 ("6F) h:=1158523+327680=1486203, hh:=95 +289: setchar98 ("62) h:=1486203+364085=1850288, hh:=118 +290: setchar110 ("6E) h:=1850288+364085=2214373, hh:=141 +291: setchar97 ("61) h:=2214373+327680=2542053, hh:=162 +292: setchar109 ("6D) h:=2542053+546111=3088164, hh:=197 +293: setchar101 ("65) h:=3088164+291275=3379439, hh:=215 +294: setchar46 ("2E) h:=3379439+182043=3561482, hh:=227 +[\jobname.] +295: pop +level 1:(h=0,v=3801088,w=0,x=0,y=786432,z=0,hh=0,vv=241) +296: y0 786432 v:=3801088+786432=4587520, vv:=291 +297: push +level 1:(h=0,v=4587520,w=0,x=0,y=786432,z=0,hh=0,vv=291) +298: push +level 2:(h=0,v=4587520,w=0,x=0,y=786432,z=0,hh=0,vv=291) +299: fntnum1 current font is min10 +300: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +303: pop +level 2:(h=0,v=4587520,w=0,x=0,y=786432,z=0,hh=0,vv=291) +304: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +308: fntnum0 current font is ec-lmr10 +309: setchar111 ("6F) h:=630598+327680=958278, hh:=61 +310: setchar110 ("6E) h:=958278+364085=1322363, hh:=84 +311: setchar101 ("65) h:=1322363+291275=1613638, hh:=102 +312: setchar108 ("6C) h:=1613638+182043=1795681, hh:=114 +313: setchar101 ("65) h:=1795681+291275=2086956, hh:=132 +314: setchar116 ("74) h:=2086956+254870=2341826, hh:=148 +315: setchar116 ("74) h:=2341826+254870=2596696, hh:=164 +316: setchar101 ("65) h:=2596696+291275=2887971, hh:=182 +317: setchar114 ("72) h:=2887971+256683=3144654, hh:=198 +318: setchar46 ("2E) h:=3144654+182043=3326697, hh:=210 +[oneletter.] +319: pop +level 1:(h=0,v=4587520,w=0,x=0,y=786432,z=0,hh=0,vv=291) +320: y0 786432 v:=4587520+786432=5373952, vv:=340 +321: push +level 1:(h=0,v=5373952,w=0,x=0,y=786432,z=0,hh=0,vv=340) +322: right3 1310720 h:=0+1310720=1310720, hh:=83 +326: setchar92 ("5C) h:=1310720+327680=1638400, hh:=104 +[ \] +327: set1 196("C4) h:=1638400+491520=2129920, hh:=135 +329: setchar46 ("2E) h:=2129920+182043=2311963, hh:=147 +330: setchar92 ("5C) h:=2311963+327680=2639643, hh:=168 +[.\] +331: set1 197("C5) h:=2639643+491520=3131163, hh:=199 +333: setchar46 ("2E) h:=3131163+182043=3313206, hh:=211 +334: setchar92 ("5C) h:=3313206+327680=3640886, hh:=232 +[.\] +335: set1 255("FF) h:=3640886+327680=3968566, hh:=253 +337: setchar46 ("2E) h:=3968566+182043=4150609, hh:=265 +338: right3 291271 h:=4150609+291271=4441880, hh:=281 +[. ] +342: set1 191("BF) h:=4441880+491520=4933400, hh:=312 +344: pop +level 1:(h=0,v=5373952,w=0,x=0,y=786432,z=0,hh=0,vv=340) +345: y0 786432 v:=5373952+786432=6160384, vv:=390 +346: push +level 1:(h=0,v=6160384,w=0,x=0,y=786432,z=0,hh=0,vv=390) +347: push +level 2:(h=0,v=6160384,w=0,x=0,y=786432,z=0,hh=0,vv=390) +348: fntnum1 current font is min10 +349: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +352: pop +level 2:(h=0,v=6160384,w=0,x=0,y=786432,z=0,hh=0,vv=390) +353: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +357: fntnum0 current font is ec-lmr10 +358: setchar99 ("63) h:=630598+291275=921873, hh:=58 +359: setchar115 ("73) h:=921873+258506=1180379, hh:=74 +360: setchar110 ("6E) h:=1180379+364085=1544464, hh:=97 +361: setchar97 ("61) h:=1544464+327680=1872144, hh:=118 +362: setchar109 ("6D) h:=1872144+546111=2418255, hh:=153 +363: setchar101 ("65) h:=2418255+291275=2709530, hh:=171 +364: setchar49 ("31) h:=2709530+327680=3037210, hh:=192 +365: setchar46 ("2E) h:=3037210+182043=3219253, hh:=204 +[csname1.] +366: pop +level 1:(h=0,v=6160384,w=0,x=0,y=786432,z=0,hh=0,vv=390) +367: y0 786432 v:=6160384+786432=6946816, vv:=440 +368: push +level 1:(h=0,v=6946816,w=0,x=0,y=786432,z=0,hh=0,vv=440) +369: right3 1310720 h:=0+1310720=1310720, hh:=83 +373: setchar92 ("5C) h:=1310720+327680=1638400, hh:=104 +[ \] +374: set1 197("C5) h:=1638400+491520=2129920, hh:=135 +376: set1 191("BF) h:=2129920+491520=2621440, hh:=166 +378: setchar92 ("5C) h:=2621440+327680=2949120, hh:=187 +[\] +379: set1 197("C5) h:=2949120+491520=3440640, hh:=218 +381: set1 191("BF) h:=3440640+491520=3932160, hh:=249 +383: setchar44 ("2C) h:=3932160+182043=4114203, hh:=261 +384: w3 218453 h:=4114203+218453=4332656, hh:=274 +388: setchar92 ("5C) h:=4332656+327680=4660336, hh:=295 +[, \] +389: set1 197("C5) h:=4660336+491520=5151856, hh:=326 +391: set1 191("BF) h:=5151856+491520=5643376, hh:=357 +393: setchar44 ("2C) h:=5643376+182043=5825419, hh:=369 +394: w0 218453 h:=5825419+218453=6043872, hh:=383 +395: setchar92 ("5C) h:=6043872+327680=6371552, hh:=404 +[, \] +396: fntnum1 current font is min10 +397: set2 17727("453F) type=0 h:=6371552+630598=7002150, hh:=444 +[䔿] +400: pop +level 1:(h=0,v=6946816,w=0,x=0,y=786432,z=0,hh=0,vv=440) +401: y0 786432 v:=6946816+786432=7733248, vv:=490 +402: push +level 1:(h=0,v=7733248,w=0,x=0,y=786432,z=0,hh=0,vv=490) +403: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +407: fntnum0 current font is ec-lmr10 +408: setchar92 ("5C) h:=1310720+327680=1638400, hh:=104 +[\] +409: fntnum1 current font is min10 +410: set2 9250("2422) type=0 h:=1638400+630598=2268998, hh:=144 +[␢] +413: fntnum0 current font is ec-lmr10 +414: setchar61 ("3D) h:=2268998+509738=2778736, hh:=176 +415: setchar62 ("3E) h:=2778736+509738=3288474, hh:=208 +416: right3 218453 h:=3288474+218453=3506927, hh:=222 +420: setchar104 ("68) h:=3506927+364085=3871012, hh:=245 +421: setchar111 ("6F) h:=3871012+327680=4198692, hh:=266 +422: setchar103 ("67) h:=4198692+327680=4526372, hh:=287 +423: setchar101 ("65) h:=4526372+291275=4817647, hh:=305 +424: setchar44 ("2C) h:=4817647+182043=4999690, hh:=317 +[=> hoge,] +425: pop +level 1:(h=0,v=7733248,w=0,x=0,y=786432,z=0,hh=0,vv=490) +426: y0 786432 v:=7733248+786432=8519680, vv:=540 +427: push +level 1:(h=0,v=8519680,w=0,x=0,y=786432,z=0,hh=0,vv=540) +428: right3 1310720 h:=0+1310720=1310720, hh:=83 +432: setchar92 ("5C) h:=1310720+327680=1638400, hh:=104 +[ \] +433: set1 164("A4) h:=1638400+364085=2002485, hh:=127 +435: set1 162("A2) h:=2002485+291275=2293760, hh:=145 +437: setchar61 ("3D) h:=2293760+509738=2803498, hh:=177 +438: setchar62 ("3E) h:=2803498+509738=3313236, hh:=209 +439: right3 218453 h:=3313236+218453=3531689, hh:=224 +443: setchar112 ("70) h:=3531689+364085=3895774, hh:=247 +444: setchar105 ("69) h:=3895774+182043=4077817, hh:=259 +445: setchar121 ("79) h:=4077817+345898=4423715, hh:=281 +446: right2 -18205 h:=4423715-18205=4405510, hh:=280 +449: setchar111 ("6F) h:=4405510+327680=4733190, hh:=301 +450: setchar44 ("2C) h:=4733190+182043=4915233, hh:=313 +[=> piyo,] +451: pop +level 1:(h=0,v=8519680,w=0,x=0,y=786432,z=0,hh=0,vv=540) +452: y0 786432 v:=8519680+786432=9306112, vv:=589 +453: push +level 1:(h=0,v=9306112,w=0,x=0,y=786432,z=0,hh=0,vv=589) +454: right3 1310720 h:=0+1310720=1310720, hh:=83 +458: setchar92 ("5C) h:=1310720+327680=1638400, hh:=104 +[ \] +459: set1 164("A4) h:=1638400+364085=2002485, hh:=127 +461: set1 162("A2) h:=2002485+291275=2293760, hh:=145 +463: setchar61 ("3D) h:=2293760+509738=2803498, hh:=177 +464: setchar62 ("3E) h:=2803498+509738=3313236, hh:=209 +465: right3 218453 h:=3313236+218453=3531689, hh:=224 +469: setchar112 ("70) h:=3531689+364085=3895774, hh:=247 +470: setchar105 ("69) h:=3895774+182043=4077817, hh:=259 +471: setchar121 ("79) h:=4077817+345898=4423715, hh:=281 +472: right2 -18205 h:=4423715-18205=4405510, hh:=280 +475: setchar111 ("6F) h:=4405510+327680=4733190, hh:=301 +476: setchar46 ("2E) h:=4733190+182043=4915233, hh:=313 +[=> piyo.] +477: pop +level 1:(h=0,v=9306112,w=0,x=0,y=786432,z=0,hh=0,vv=589) +478: y0 786432 v:=9306112+786432=10092544, vv:=639 +479: push +level 1:(h=0,v=10092544,w=0,x=0,y=786432,z=0,hh=0,vv=639) +480: push +level 2:(h=0,v=10092544,w=0,x=0,y=786432,z=0,hh=0,vv=639) +481: fntnum1 current font is min10 +482: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +485: pop +level 2:(h=0,v=10092544,w=0,x=0,y=786432,z=0,hh=0,vv=639) +486: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +490: fntnum0 current font is ec-lmr10 +491: setchar48 ("30) h:=630598+327680=958278, hh:=61 +492: setchar120 ("78) h:=958278+345898=1304176, hh:=83 +493: setchar70 ("46) h:=1304176+427818=1731994, hh:=110 +494: setchar70 ("46) h:=1731994+427818=2159812, hh:=137 +495: setchar46 ("2E) h:=2159812+182043=2341855, hh:=149 +[0xFF.] +496: pop +level 1:(h=0,v=10092544,w=0,x=0,y=786432,z=0,hh=0,vv=639) +497: y0 786432 v:=10092544+786432=10878976, vv:=689 +498: push +level 1:(h=0,v=10878976,w=0,x=0,y=786432,z=0,hh=0,vv=689) +499: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +503: fntnum1 current font is min10 +504: set2 9250("2422) type=0 h:=1310720+630598=1941318, hh:=123 +[␢] +507: fntnum0 current font is ec-lmr10 +508: setchar44 ("2C) h:=1941318+182043=2123361, hh:=135 +509: w3 218453 h:=2123361+218453=2341814, hh:=148 +513: setchar40 ("28) h:=2341814+254870=2596684, hh:=164 +514: setchar92 ("5C) h:=2596684+327680=2924364, hh:=185 +[, (\] +515: set1 255("FF) h:=2924364+327680=3252044, hh:=206 +517: set1 197("C5) h:=3252044+491520=3743564, hh:=237 +519: set1 255("FF) h:=3743564+327680=4071244, hh:=258 +521: set1 191("BF) h:=4071244+491520=4562764, hh:=289 +523: setchar58 ("3A) h:=4562764+182043=4744807, hh:=301 +524: setchar109 ("6D) h:=4744807+546111=5290918, hh:=336 +525: setchar97 ("61) h:=5290918+327680=5618598, hh:=357 +526: setchar99 ("63) h:=5618598+291275=5909873, hh:=375 +527: setchar114 ("72) h:=5909873+256683=6166556, hh:=391 +528: setchar111 ("6F) h:=6166556+327680=6494236, hh:=412 +529: setchar58 ("3A) h:=6494236+182043=6676279, hh:=424 +530: setchar45 ("2D) h:=6676279+218453=6894732, hh:=438 +531: setchar62 ("3E) h:=6894732+509738=7404470, hh:=470 +[:macro:->] +532: fntnum1 current font is min10 +533: set2 9250("2422) type=0 h:=7404470+630598=8035068, hh:=510 +[␢] +536: fntnum0 current font is ec-lmr10 +537: setchar41 ("29) h:=8035068+254870=8289938, hh:=526 +538: setchar44 ("2C) h:=8289938+182043=8471981, hh:=538 +539: w0 218453 h:=8471981+218453=8690434, hh:=550 +540: setchar92 ("5C) h:=8690434+327680=9018114, hh:=571 +[), \] +541: set1 255("FF) h:=9018114+327680=9345794, hh:=592 +543: set1 197("C5) h:=9345794+491520=9837314, hh:=623 +545: set1 255("FF) h:=9837314+327680=10164994, hh:=644 +547: set1 191("BF) h:=10164994+491520=10656514, hh:=675 +549: setchar44 ("2C) h:=10656514+182043=10838557, hh:=687 +550: w0 218453 h:=10838557+218453=11057010, hh:=700 +551: setchar109 ("6D) h:=11057010+546111=11603121, hh:=735 +552: setchar97 ("61) h:=11603121+327680=11930801, hh:=756 +553: setchar99 ("63) h:=11930801+291275=12222076, hh:=774 +554: setchar114 ("72) h:=12222076+256683=12478759, hh:=790 +555: setchar111 ("6F) h:=12478759+327680=12806439, hh:=811 +556: setchar58 ("3A) h:=12806439+182043=12988482, hh:=823 +557: setchar45 ("2D) h:=12988482+218453=13206935, hh:=837 +558: setchar62 ("3E) h:=13206935+509738=13716673, hh:=869 +559: setchar40 ("28) h:=13716673+254870=13971543, hh:=885 +560: setchar92 ("5C) h:=13971543+327680=14299223, hh:=906 +[, macro:->(\] +561: set1 255("FF) h:=14299223+327680=14626903, hh:=927 +563: set1 197("C5) h:=14626903+491520=15118423, hh:=958 +565: set1 255("FF) h:=15118423+327680=15446103, hh:=979 +567: set1 191("BF) h:=15446103+491520=15937623, hh:=1010 +569: setchar58 ("3A) h:=15937623+182043=16119666, hh:=1022 +570: setchar109 ("6D) h:=16119666+546111=16665777, hh:=1057 +571: setchar97 ("61) h:=16665777+327680=16993457, hh:=1078 +572: setchar99 ("63) h:=16993457+291275=17284732, hh:=1096 +573: setchar114 ("72) h:=17284732+256683=17541415, hh:=1112 +574: setchar111 ("6F) h:=17541415+327680=17869095, hh:=1133 +575: setchar58 ("3A) h:=17869095+182043=18051138, hh:=1145 +576: setchar45 ("2D) h:=18051138+218453=18269591, hh:=1159 +577: setchar62 ("3E) h:=18269591+509738=18779329, hh:=1191 +[:macro:->] +578: fntnum1 current font is min10 +579: set2 9250("2422) type=0 h:=18779329+630598=19409927, hh:=1231 +[␢] +582: fntnum0 current font is ec-lmr10 +583: setchar41 ("29) h:=19409927+254870=19664797, hh:=1247 +584: setchar46 ("2E) h:=19664797+182043=19846840, hh:=1259 +[).] +585: pop +level 1:(h=0,v=10878976,w=0,x=0,y=786432,z=0,hh=0,vv=689) +586: y0 786432 v:=10878976+786432=11665408, vv:=739 +587: push +level 1:(h=0,v=11665408,w=0,x=0,y=786432,z=0,hh=0,vv=739) +588: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +592: fntnum1 current font is min10 +593: set2 9252("2424) type=0 h:=1310720+630598=1941318, hh:=123 +[␤] +596: fntnum0 current font is ec-lmr10 +597: setchar44 ("2C) h:=1941318+182043=2123361, hh:=135 +598: w3 218453 h:=2123361+218453=2341814, hh:=148 +602: setchar40 ("28) h:=2341814+254870=2596684, hh:=164 +603: setchar92 ("5C) h:=2596684+327680=2924364, hh:=185 +[, (\] +604: set1 255("FF) h:=2924364+327680=3252044, hh:=206 +606: setchar58 ("3A) h:=3252044+182043=3434087, hh:=218 +607: setchar109 ("6D) h:=3434087+546111=3980198, hh:=253 +608: setchar97 ("61) h:=3980198+327680=4307878, hh:=274 +609: setchar99 ("63) h:=4307878+291275=4599153, hh:=292 +610: setchar114 ("72) h:=4599153+256683=4855836, hh:=308 +611: setchar111 ("6F) h:=4855836+327680=5183516, hh:=329 +612: setchar58 ("3A) h:=5183516+182043=5365559, hh:=341 +613: setchar45 ("2D) h:=5365559+218453=5584012, hh:=355 +614: setchar62 ("3E) h:=5584012+509738=6093750, hh:=387 +[:macro:->] +615: fntnum1 current font is min10 +616: set2 9252("2424) type=0 h:=6093750+630598=6724348, hh:=427 +[␤] +619: fntnum0 current font is ec-lmr10 +620: setchar41 ("29) h:=6724348+254870=6979218, hh:=443 +621: setchar44 ("2C) h:=6979218+182043=7161261, hh:=455 +622: w0 218453 h:=7161261+218453=7379714, hh:=467 +623: setchar92 ("5C) h:=7379714+327680=7707394, hh:=488 +[), \] +624: set1 255("FF) h:=7707394+327680=8035074, hh:=509 +626: setchar44 ("2C) h:=8035074+182043=8217117, hh:=521 +627: w0 218453 h:=8217117+218453=8435570, hh:=534 +628: setchar109 ("6D) h:=8435570+546111=8981681, hh:=569 +629: setchar97 ("61) h:=8981681+327680=9309361, hh:=590 +630: setchar99 ("63) h:=9309361+291275=9600636, hh:=608 +631: setchar114 ("72) h:=9600636+256683=9857319, hh:=624 +632: setchar111 ("6F) h:=9857319+327680=10184999, hh:=645 +633: setchar58 ("3A) h:=10184999+182043=10367042, hh:=657 +634: setchar45 ("2D) h:=10367042+218453=10585495, hh:=671 +635: setchar62 ("3E) h:=10585495+509738=11095233, hh:=703 +636: setchar40 ("28) h:=11095233+254870=11350103, hh:=719 +637: setchar92 ("5C) h:=11350103+327680=11677783, hh:=740 +[, macro:->(\] +638: set1 255("FF) h:=11677783+327680=12005463, hh:=761 +640: setchar58 ("3A) h:=12005463+182043=12187506, hh:=773 +641: setchar109 ("6D) h:=12187506+546111=12733617, hh:=808 +642: setchar97 ("61) h:=12733617+327680=13061297, hh:=829 +643: setchar99 ("63) h:=13061297+291275=13352572, hh:=847 +644: setchar114 ("72) h:=13352572+256683=13609255, hh:=863 +645: setchar111 ("6F) h:=13609255+327680=13936935, hh:=884 +646: setchar58 ("3A) h:=13936935+182043=14118978, hh:=896 +647: setchar45 ("2D) h:=14118978+218453=14337431, hh:=910 +648: setchar62 ("3E) h:=14337431+509738=14847169, hh:=942 +[:macro:->] +649: fntnum1 current font is min10 +650: set2 9252("2424) type=0 h:=14847169+630598=15477767, hh:=982 +[␤] +653: fntnum0 current font is ec-lmr10 +654: setchar41 ("29) h:=15477767+254870=15732637, hh:=998 +655: setchar46 ("2E) h:=15732637+182043=15914680, hh:=1010 +[).] +656: pop +level 1:(h=0,v=11665408,w=0,x=0,y=786432,z=0,hh=0,vv=739) +657: y0 786432 v:=11665408+786432=12451840, vv:=789 +658: push +level 1:(h=0,v=12451840,w=0,x=0,y=786432,z=0,hh=0,vv=789) +659: push +level 2:(h=0,v=12451840,w=0,x=0,y=786432,z=0,hh=0,vv=789) +660: fntnum1 current font is min10 +661: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +664: pop +level 2:(h=0,v=12451840,w=0,x=0,y=786432,z=0,hh=0,vv=789) +665: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +669: fntnum0 current font is ec-lmr10 +670: setchar99 ("63) h:=630598+291275=921873, hh:=58 +671: setchar111 ("6F) h:=921873+327680=1249553, hh:=79 +672: setchar110 ("6E) h:=1249553+364085=1613638, hh:=102 +673: right2 -18205 h:=1613638-18205=1595433, hh:=101 +676: setchar116 ("74) h:=1595433+254870=1850303, hh:=117 +677: setchar101 ("65) h:=1850303+291275=2141578, hh:=135 +678: setchar120 ("78) h:=2141578+345898=2487476, hh:=157 +679: setchar116 ("74) h:=2487476+254870=2742346, hh:=173 +680: setchar115 ("73) h:=2742346+258506=3000852, hh:=189 +681: setchar46 ("2E) h:=3000852+182043=3182895, hh:=201 +[contexts.] +682: pop +level 1:(h=0,v=12451840,w=0,x=0,y=786432,z=0,hh=0,vv=789) +683: y0 786432 v:=12451840+786432=13238272, vv:=839 +684: push +level 1:(h=0,v=13238272,w=0,x=0,y=786432,z=0,hh=0,vv=839) +685: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +689: fntnum1 current font is min10 +690: set2 9250("2422) type=0 h:=1310720+630598=1941318, hh:=123 +[␢] +693: fntnum0 current font is ec-lmr10 +694: set1 197("C5) h:=1941318+491520=2432838, hh:=154 +696: set1 191("BF) h:=2432838+491520=2924358, hh:=185 +698: w3 218453 h:=2924358+218453=3142811, hh:=199 +702: setchar97 ("61) h:=3142811+327680=3470491, hh:=220 +[ a] +703: set1 197("C5) h:=3470491+491520=3962011, hh:=251 +705: set1 191("BF) h:=3962011+491520=4453531, hh:=282 +707: w0 218453 h:=4453531+218453=4671984, hh:=296 +[ ] +708: set1 197("C5) h:=4671984+491520=5163504, hh:=327 +710: set1 191("BF) h:=5163504+491520=5655024, hh:=358 +712: w0 218453 h:=5655024+218453=5873477, hh:=372 +[ ] +713: fntnum1 current font is min10 +714: set2 17727("453F) type=0 h:=5873477+630598=6504075, hh:=412 +717: w0 218453 h:=6504075+218453=6722528, hh:=426 +[䔿 ] +718: fntnum0 current font is ec-lmr10 +719: set1 197("C5) h:=6722528+491520=7214048, hh:=457 +721: set1 191("BF) h:=7214048+491520=7705568, hh:=488 +723: w0 218453 h:=7705568+218453=7924021, hh:=502 +[ ] +724: set1 197("C5) h:=7924021+491520=8415541, hh:=533 +726: set1 191("BF) h:=8415541+491520=8907061, hh:=564 +728: w0 218453 h:=8907061+218453=9125514, hh:=578 +[ ] +729: fntnum1 current font is min10 +730: set2 17727("453F) type=0 h:=9125514+630598=9756112, hh:=618 +733: x3 436906 h:=9756112+436906=10193018, hh:=646 +[䔿 ] +737: fntnum0 current font is ec-lmr10 +738: set1 197("C5) h:=10193018+491520=10684538, hh:=677 +740: set1 191("BF) h:=10684538+491520=11176058, hh:=708 +742: w0 218453 h:=11176058+218453=11394511, hh:=722 +[ ] +743: fntnum1 current font is min10 +744: set2 17727("453F) type=0 h:=11394511+630598=12025109, hh:=762 +747: x0 436906 h:=12025109+436906=12462015, hh:=789 +748: set2 9252("2424) type=0 h:=12462015+630598=13092613, hh:=829 +[䔿 ␤] +751: fntnum0 current font is ec-lmr10 +752: setchar109 ("6D) h:=13092613+546111=13638724, hh:=864 +753: setchar97 ("61) h:=13638724+327680=13966404, hh:=885 +754: setchar99 ("63) h:=13966404+291275=14257679, hh:=903 +755: setchar114 ("72) h:=14257679+256683=14514362, hh:=919 +756: setchar111 ("6F) h:=14514362+327680=14842042, hh:=940 +757: setchar58 ("3A) h:=14842042+182043=15024085, hh:=952 +758: setchar45 ("2D) h:=15024085+218453=15242538, hh:=966 +759: setchar62 ("3E) h:=15242538+509738=15752276, hh:=998 +[macro:->] +760: set1 197("C5) h:=15752276+491520=16243796, hh:=1029 +762: set1 191("BF) h:=16243796+491520=16735316, hh:=1060 +764: w0 218453 h:=16735316+218453=16953769, hh:=1074 +[ ] +765: set1 197("C5) h:=16953769+491520=17445289, hh:=1105 +767: set1 191("BF) h:=17445289+491520=17936809, hh:=1136 +769: w0 218453 h:=17936809+218453=18155262, hh:=1150 +[ ] +770: fntnum1 current font is min10 +771: set2 17727("453F) type=0 h:=18155262+630598=18785860, hh:=1190 +[䔿] +774: pop +level 1:(h=0,v=13238272,w=0,x=0,y=786432,z=0,hh=0,vv=839) +775: y0 786432 v:=13238272+786432=14024704, vv:=888 +776: push +level 1:(h=0,v=14024704,w=0,x=0,y=786432,z=0,hh=0,vv=888) +777: right3 1310720 h:=0+1310720=1310720, hh:=83 +781: set2 9250("2422) type=0 h:=1310720+630598=1941318, hh:=123 +[ ␢] +784: fntnum0 current font is ec-lmr10 +785: set1 197("C5) h:=1941318+491520=2432838, hh:=154 +787: set1 191("BF) h:=2432838+491520=2924358, hh:=185 +789: w3 218453 h:=2924358+218453=3142811, hh:=199 +[ ] +793: set1 197("C5) h:=3142811+491520=3634331, hh:=230 +795: set1 191("BF) h:=3634331+491520=4125851, hh:=261 +797: fntnum1 current font is min10 +798: set2 17727("453F) type=0 h:=4125851+630598=4756449, hh:=301 +[䔿] +801: fntnum0 current font is ec-lmr10 +802: set1 197("C5) h:=4756449+491520=5247969, hh:=332 +804: set1 191("BF) h:=5247969+491520=5739489, hh:=363 +806: w0 218453 h:=5739489+218453=5957942, hh:=377 +807: setchar97 ("61) h:=5957942+327680=6285622, hh:=398 +[ a] +808: set1 197("C5) h:=6285622+491520=6777142, hh:=429 +810: set1 191("BF) h:=6777142+491520=7268662, hh:=460 +812: w0 218453 h:=7268662+218453=7487115, hh:=474 +[ ] +813: set1 197("C5) h:=7487115+491520=7978635, hh:=505 +815: set1 191("BF) h:=7978635+491520=8470155, hh:=536 +817: w0 218453 h:=8470155+218453=8688608, hh:=550 +[ ] +818: fntnum1 current font is min10 +819: set2 17727("453F) type=0 h:=8688608+630598=9319206, hh:=590 +822: w0 218453 h:=9319206+218453=9537659, hh:=604 +[䔿 ] +823: fntnum0 current font is ec-lmr10 +824: set1 197("C5) h:=9537659+491520=10029179, hh:=635 +826: set1 191("BF) h:=10029179+491520=10520699, hh:=666 +828: w0 218453 h:=10520699+218453=10739152, hh:=680 +[ ] +829: set1 197("C5) h:=10739152+491520=11230672, hh:=711 +831: set1 191("BF) h:=11230672+491520=11722192, hh:=742 +833: w0 218453 h:=11722192+218453=11940645, hh:=756 +[ ] +834: fntnum1 current font is min10 +835: set2 17727("453F) type=0 h:=11940645+630598=12571243, hh:=796 +838: right3 436906 h:=12571243+436906=13008149, hh:=824 +[䔿 ] +842: fntnum0 current font is ec-lmr10 +843: set1 197("C5) h:=13008149+491520=13499669, hh:=855 +845: set1 191("BF) h:=13499669+491520=13991189, hh:=886 +847: w0 218453 h:=13991189+218453=14209642, hh:=900 +[ ] +848: fntnum1 current font is min10 +849: set2 17727("453F) type=0 h:=14209642+630598=14840240, hh:=940 +852: w0 218453 h:=14840240+218453=15058693, hh:=954 +853: set2 9252("2424) type=0 h:=15058693+630598=15689291, hh:=994 +[䔿 ␤] +856: fntnum0 current font is ec-lmr10 +857: set1 255("FF) h:=15689291+327680=16016971, hh:=1015 +859: pop +level 1:(h=0,v=14024704,w=0,x=0,y=786432,z=0,hh=0,vv=888) +860: y0 786432 v:=14024704+786432=14811136, vv:=938 +861: push +level 1:(h=0,v=14811136,w=0,x=0,y=786432,z=0,hh=0,vv=938) +862: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +866: fntnum1 current font is min10 +867: set2 9252("2424) type=0 h:=1310720+630598=1941318, hh:=123 +[␤] +870: pop +level 1:(h=0,v=14811136,w=0,x=0,y=786432,z=0,hh=0,vv=938) +871: y0 786432 v:=14811136+786432=15597568, vv:=988 +872: push +level 1:(h=0,v=15597568,w=0,x=0,y=786432,z=0,hh=0,vv=988) +873: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +877: fntnum0 current font is ec-lmr10 +878: setchar46 ("2E) h:=1310720+182043=1492763, hh:=95 +879: setchar97 ("61) h:=1492763+327680=1820443, hh:=116 +880: setchar46 ("2E) h:=1820443+182043=2002486, hh:=128 +881: setchar46 ("2E) h:=2002486+182043=2184529, hh:=140 +882: setchar46 ("2E) h:=2184529+182043=2366572, hh:=152 +883: setchar99 ("63) h:=2366572+291275=2657847, hh:=170 +884: setchar46 ("2E) h:=2657847+182043=2839890, hh:=182 +885: setchar98 ("62) h:=2839890+364085=3203975, hh:=205 +886: setchar46 ("2E) h:=3203975+182043=3386018, hh:=216 +887: setchar46 ("2E) h:=3386018+182043=3568061, hh:=228 +[.a...c.b..] +888: pop +level 1:(h=0,v=15597568,w=0,x=0,y=786432,z=0,hh=0,vv=988) +889: y0 786432 v:=15597568+786432=16384000, vv:=1038 +890: push +level 1:(h=0,v=16384000,w=0,x=0,y=786432,z=0,hh=0,vv=1038) +891: right3 1310720 h:=0+1310720=1310720, hh:=83 +895: setchar46 ("2E) h:=1310720+182043=1492763, hh:=95 +896: setchar97 ("61) h:=1492763+327680=1820443, hh:=116 +897: setchar46 ("2E) h:=1820443+182043=2002486, hh:=128 +898: setchar46 ("2E) h:=2002486+182043=2184529, hh:=140 +899: setchar46 ("2E) h:=2184529+182043=2366572, hh:=152 +900: setchar99 ("63) h:=2366572+291275=2657847, hh:=170 +901: setchar46 ("2E) h:=2657847+182043=2839890, hh:=182 +902: setchar98 ("62) h:=2839890+364085=3203975, hh:=205 +903: setchar46 ("2E) h:=3203975+182043=3386018, hh:=216 +904: setchar46 ("2E) h:=3386018+182043=3568061, hh:=228 +[ .a...c.b..] +905: pop +level 1:(h=0,v=16384000,w=0,x=0,y=786432,z=0,hh=0,vv=1038) +906: y0 786432 v:=16384000+786432=17170432, vv:=1088 +907: push +level 1:(h=0,v=17170432,w=0,x=0,y=786432,z=0,hh=0,vv=1088) +908: push +level 2:(h=0,v=17170432,w=0,x=0,y=786432,z=0,hh=0,vv=1088) +909: fntnum1 current font is min10 +910: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +913: pop +level 2:(h=0,v=17170432,w=0,x=0,y=786432,z=0,hh=0,vv=1088) +914: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +918: fntnum0 current font is ec-lmr10 +919: setchar99 ("63) h:=630598+291275=921873, hh:=58 +920: setchar115 ("73) h:=921873+258506=1180379, hh:=74 +921: setchar110 ("6E) h:=1180379+364085=1544464, hh:=97 +922: setchar97 ("61) h:=1544464+327680=1872144, hh:=118 +923: setchar109 ("6D) h:=1872144+546111=2418255, hh:=153 +924: setchar101 ("65) h:=2418255+291275=2709530, hh:=171 +925: setchar50 ("32) h:=2709530+327680=3037210, hh:=192 +926: setchar46 ("2E) h:=3037210+182043=3219253, hh:=204 +[csname2.] +927: pop +level 1:(h=0,v=17170432,w=0,x=0,y=786432,z=0,hh=0,vv=1088) +928: y0 786432 v:=17170432+786432=17956864, vv:=1137 +929: push +level 1:(h=0,v=17956864,w=0,x=0,y=786432,z=0,hh=0,vv=1137) +930: right3 1310720 h:=0+1310720=1310720, hh:=83 +934: setchar83 ("53) h:=1310720+364085=1674805, hh:=106 +935: setchar72 ("48) h:=1674805+491520=2166325, hh:=137 +936: setchar79 ("4F) h:=2166325+509738=2676063, hh:=169 +937: right2 -18205 h:=2676063-18205=2657858, hh:=168 +940: setchar87 ("57) h:=2657858+673578=3331436, hh:=211 +941: right3 218453 h:=3331436+218453=3549889, hh:=225 +945: setchar46 ("2E) h:=3549889+182043=3731932, hh:=237 +946: setchar46 ("2E) h:=3731932+182043=3913975, hh:=249 +947: setchar46 ("2E) h:=3913975+182043=4096018, hh:=261 +[ SHOW ...] +948: pop +level 1:(h=0,v=17956864,w=0,x=0,y=786432,z=0,hh=0,vv=1137) +949: y0 786432 v:=17956864+786432=18743296, vv:=1187 +950: push +level 1:(h=0,v=18743296,w=0,x=0,y=786432,z=0,hh=0,vv=1187) +951: right3 1310720 h:=0+1310720=1310720, hh:=83 +955: setchar83 ("53) h:=1310720+364085=1674805, hh:=106 +956: setchar84 ("54) h:=1674805+473301=2148106, hh:=136 +957: setchar82 ("52) h:=2148106+482410=2630516, hh:=167 +958: setchar73 ("49) h:=2630516+236650=2867166, hh:=182 +959: setchar78 ("4E) h:=2867166+491520=3358686, hh:=213 +960: setchar71 ("47) h:=3358686+514261=3872947, hh:=246 +961: right3 218453 h:=3872947+218453=4091400, hh:=259 +965: setchar92 ("5C) h:=4091400+327680=4419080, hh:=280 +[ STRING \] +966: set1 197("C5) h:=4419080+491520=4910600, hh:=311 +968: set1 191("BF) h:=4910600+491520=5402120, hh:=342 +970: setchar46 ("2E) h:=5402120+182043=5584163, hh:=354 +971: setchar92 ("5C) h:=5584163+327680=5911843, hh:=375 +[.\] +972: fntnum1 current font is min10 +973: set2 17727("453F) type=0 h:=5911843+630598=6542441, hh:=415 +[䔿] +976: fntnum0 current font is ec-lmr10 +977: setchar46 ("2E) h:=6542441+182043=6724484, hh:=427 +978: setchar92 ("5C) h:=6724484+327680=7052164, hh:=448 +[.\] +979: set1 197("C5) h:=7052164+491520=7543684, hh:=479 +981: set1 191("BF) h:=7543684+491520=8035204, hh:=510 +983: setchar46 ("2E) h:=8035204+182043=8217247, hh:=522 +984: setchar92 ("5C) h:=8217247+327680=8544927, hh:=543 +[.\] +985: fntnum1 current font is min10 +986: set2 17727("453F) type=0 h:=8544927+630598=9175525, hh:=583 +[䔿] +989: pop +level 1:(h=0,v=18743296,w=0,x=0,y=786432,z=0,hh=0,vv=1187) +990: y0 786432 v:=18743296+786432=19529728, vv:=1237 +991: push +level 1:(h=0,v=19529728,w=0,x=0,y=786432,z=0,hh=0,vv=1237) +992: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +996: fntnum0 current font is ec-lmr10 +997: setchar77 ("4D) h:=1310720+600768=1911488, hh:=121 +998: setchar69 ("45) h:=1911488+446005=2357493, hh:=149 +999: setchar65 ("41) h:=2357493+491520=2849013, hh:=180 +1000: setchar78 ("4E) h:=2849013+491520=3340533, hh:=211 +1001: setchar73 ("49) h:=3340533+236650=3577183, hh:=226 +1002: setchar78 ("4E) h:=3577183+491520=4068703, hh:=257 +1003: setchar71 ("47) h:=4068703+514261=4582964, hh:=290 +1004: right3 218453 h:=4582964+218453=4801417, hh:=304 +1008: setchar109 ("6D) h:=4801417+546111=5347528, hh:=339 +1009: setchar97 ("61) h:=5347528+327680=5675208, hh:=360 +1010: setchar99 ("63) h:=5675208+291275=5966483, hh:=378 +1011: setchar114 ("72) h:=5966483+256683=6223166, hh:=394 +1012: setchar111 ("6F) h:=6223166+327680=6550846, hh:=415 +1013: setchar58 ("3A) h:=6550846+182043=6732889, hh:=427 +1014: setchar45 ("2D) h:=6732889+218453=6951342, hh:=441 +1015: setchar62 ("3E) h:=6951342+509738=7461080, hh:=473 +1016: setchar97 ("61) h:=7461080+327680=7788760, hh:=494 +1017: setchar46 ("2E) h:=7788760+182043=7970803, hh:=506 +1018: setchar109 ("6D) h:=7970803+546111=8516914, hh:=541 +1019: setchar97 ("61) h:=8516914+327680=8844594, hh:=562 +1020: setchar99 ("63) h:=8844594+291275=9135869, hh:=580 +1021: setchar114 ("72) h:=9135869+256683=9392552, hh:=596 +1022: setchar111 ("6F) h:=9392552+327680=9720232, hh:=617 +1023: setchar58 ("3A) h:=9720232+182043=9902275, hh:=629 +1024: setchar45 ("2D) h:=9902275+218453=10120728, hh:=643 +1025: setchar62 ("3E) h:=10120728+509738=10630466, hh:=675 +1026: setchar98 ("62) h:=10630466+364085=10994551, hh:=698 +1027: setchar46 ("2E) h:=10994551+182043=11176594, hh:=710 +1028: setchar109 ("6D) h:=11176594+546111=11722705, hh:=745 +1029: setchar97 ("61) h:=11722705+327680=12050385, hh:=765 +1030: setchar99 ("63) h:=12050385+291275=12341660, hh:=783 +1031: setchar114 ("72) h:=12341660+256683=12598343, hh:=799 +1032: setchar111 ("6F) h:=12598343+327680=12926023, hh:=820 +1033: setchar58 ("3A) h:=12926023+182043=13108066, hh:=832 +1034: setchar45 ("2D) h:=13108066+218453=13326519, hh:=846 +1035: setchar62 ("3E) h:=13326519+509738=13836257, hh:=878 +1036: setchar97 ("61) h:=13836257+327680=14163937, hh:=899 +1037: setchar46 ("2E) h:=14163937+182043=14345980, hh:=911 +1038: setchar109 ("6D) h:=14345980+546111=14892091, hh:=945 +1039: setchar97 ("61) h:=14892091+327680=15219771, hh:=966 +1040: setchar99 ("63) h:=15219771+291275=15511046, hh:=984 +1041: setchar114 ("72) h:=15511046+256683=15767729, hh:=1000 +1042: setchar111 ("6F) h:=15767729+327680=16095409, hh:=1021 +1043: setchar58 ("3A) h:=16095409+182043=16277452, hh:=1033 +1044: setchar45 ("2D) h:=16277452+218453=16495905, hh:=1047 +1045: setchar62 ("3E) h:=16495905+509738=17005643, hh:=1079 +1046: setchar98 ("62) h:=17005643+364085=17369728, hh:=1102 +1047: setchar46 ("2E) h:=17369728+182043=17551771, hh:=1114 +[MEANING macro:->a.macro:->b.macro:->a.macro:->b.] +1048: pop +level 1:(h=0,v=19529728,w=0,x=0,y=786432,z=0,hh=0,vv=1237) +1049: pop +level 0:(h=0,v=42152922,w=0,x=0,y=0,z=0,hh=0,vv=2670) +1050: down3 1572864 v:=42152922+1572864=43725786, vv:=2770 +1054: eop diff --git a/source/texk/web2c/ptexdir/tests/p-pknj-sa.typ b/source/texk/web2c/ptexdir/tests/p-pknj-sa.typ new file mode 100644 index 000000000..9373f0bac --- /dev/null +++ b/source/texk/web2c/ptexdir/tests/p-pknj-sa.typ @@ -0,0 +1,829 @@ +Options selected: + Starting page = * + Maximum number of pages = 1000000 + Output level = 4 (the works) + Resolution = 300.00000000 pixels per inch +numerator/denominator=25400000/473628672 +magnification=1000; 0.00006334 pixels per DVI unit +' TeX output 20XX.XX.XX' +Postamble starts at byte 1061. +maxv=43725786, maxh=30785863, maxstackdepth=3, totalpages=1 +Font 1: min10 (JFM)---loaded at size 655360 DVI units +Font 0: ec-lmr10---loaded at size 655360 DVI units + +42: beginning of page 37726 +87: push +level 0:(h=0,v=0,w=0,x=0,y=0,z=0,hh=0,vv=0) +88: down3 -917504 v:=0-917504=-917504, vv:=-58 +92: pop +level 0:(h=0,v=0,w=0,x=0,y=0,z=0,hh=0,vv=0) +93: down4 42152922 v:=0+42152922=42152922, vv:=2670 +98: push +level 0:(h=0,v=42152922,w=0,x=0,y=0,z=0,hh=0,vv=2670) +99: down4 -41497562 v:=42152922-41497562=655360, vv:=42 +104: push +level 1:(h=0,v=655360,w=0,x=0,y=0,z=0,hh=0,vv=42) +105: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +109: fntdef1 0: ec-lmr10 +133: fntnum0 current font is ec-lmr10 +134: setchar65 ("41) h:=1310720+491520=1802240, hh:=114 +135: setchar58 ("3A) h:=1802240+182043=1984283, hh:=126 +136: w3 218453 h:=1984283+218453=2202736, hh:=140 +[A: ] +140: set1 197("C5) h:=2202736+491520=2694256, hh:=171 +142: set1 191("BF) h:=2694256+491520=3185776, hh:=202 +144: w0 218453 h:=3185776+218453=3404229, hh:=216 +[ ] +145: set1 197("C5) h:=3404229+491520=3895749, hh:=247 +147: set1 191("BF) h:=3895749+491520=4387269, hh:=278 +149: w0 218453 h:=4387269+218453=4605722, hh:=292 +[ ] +150: fntdef1 1: min10 +171: fntnum1 current font is min10 +172: set2 17727("453F) type=0 h:=4605722+630598=5236320, hh:=332 +[䔿] +175: pop +level 1:(h=0,v=655360,w=0,x=0,y=0,z=0,hh=0,vv=42) +176: y3 786432 v:=655360+786432=1441792, vv:=91 +180: push +level 1:(h=0,v=1441792,w=0,x=0,y=786432,z=0,hh=0,vv=91) +181: push +level 2:(h=0,v=1441792,w=0,x=0,y=786432,z=0,hh=0,vv=91) +182: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +185: pop +level 2:(h=0,v=1441792,w=0,x=0,y=786432,z=0,hh=0,vv=91) +186: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +190: fntnum0 current font is ec-lmr10 +191: setchar92 ("5C) h:=630598+327680=958278, hh:=61 +192: setchar109 ("6D) h:=958278+546111=1504389, hh:=96 +193: setchar101 ("65) h:=1504389+291275=1795664, hh:=114 +194: setchar97 ("61) h:=1795664+327680=2123344, hh:=135 +195: setchar110 ("6E) h:=2123344+364085=2487429, hh:=158 +196: setchar105 ("69) h:=2487429+182043=2669472, hh:=170 +197: setchar110 ("6E) h:=2669472+364085=3033557, hh:=193 +198: setchar103 ("67) h:=3033557+327680=3361237, hh:=214 +199: setchar46 ("2E) h:=3361237+182043=3543280, hh:=226 +[\meaning.] +200: pop +level 1:(h=0,v=1441792,w=0,x=0,y=786432,z=0,hh=0,vv=91) +201: y0 786432 v:=1441792+786432=2228224, vv:=141 +202: push +level 1:(h=0,v=2228224,w=0,x=0,y=786432,z=0,hh=0,vv=141) +203: right3 1310720 h:=0+1310720=1310720, hh:=83 +207: setchar109 ("6D) h:=1310720+546111=1856831, hh:=118 +208: setchar97 ("61) h:=1856831+327680=2184511, hh:=139 +209: setchar99 ("63) h:=2184511+291275=2475786, hh:=157 +210: setchar114 ("72) h:=2475786+256683=2732469, hh:=173 +211: setchar111 ("6F) h:=2732469+327680=3060149, hh:=194 +212: setchar58 ("3A) h:=3060149+182043=3242192, hh:=206 +213: setchar45 ("2D) h:=3242192+218453=3460645, hh:=220 +214: setchar62 ("3E) h:=3460645+509738=3970383, hh:=252 +215: setchar109 ("6D) h:=3970383+546111=4516494, hh:=287 +216: setchar97 ("61) h:=4516494+327680=4844174, hh:=308 +217: setchar99 ("63) h:=4844174+291275=5135449, hh:=326 +218: setchar114 ("72) h:=5135449+256683=5392132, hh:=342 +219: setchar111 ("6F) h:=5392132+327680=5719812, hh:=363 +220: setchar58 ("3A) h:=5719812+182043=5901855, hh:=375 +221: setchar45 ("2D) h:=5901855+218453=6120308, hh:=389 +222: setchar62 ("3E) h:=6120308+509738=6630046, hh:=421 +[ macro:->macro:->] +223: set1 197("C5) h:=6630046+491520=7121566, hh:=452 +225: set1 191("BF) h:=7121566+491520=7613086, hh:=483 +227: w3 218453 h:=7613086+218453=7831539, hh:=496 +[ ] +231: set1 197("C5) h:=7831539+491520=8323059, hh:=527 +233: set1 191("BF) h:=8323059+491520=8814579, hh:=558 +235: w0 218453 h:=8814579+218453=9033032, hh:=572 +[ ] +236: fntnum1 current font is min10 +237: set2 17727("453F) type=0 h:=9033032+630598=9663630, hh:=612 +[䔿] +240: pop +level 1:(h=0,v=2228224,w=0,x=0,y=786432,z=0,hh=0,vv=141) +241: y0 786432 v:=2228224+786432=3014656, vv:=191 +242: push +level 1:(h=0,v=3014656,w=0,x=0,y=786432,z=0,hh=0,vv=191) +243: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +247: fntnum0 current font is ec-lmr10 +248: setchar109 ("6D) h:=1310720+546111=1856831, hh:=118 +249: setchar97 ("61) h:=1856831+327680=2184511, hh:=139 +250: setchar99 ("63) h:=2184511+291275=2475786, hh:=157 +251: setchar114 ("72) h:=2475786+256683=2732469, hh:=173 +252: setchar111 ("6F) h:=2732469+327680=3060149, hh:=194 +253: setchar58 ("3A) h:=3060149+182043=3242192, hh:=206 +254: setchar45 ("2D) h:=3242192+218453=3460645, hh:=220 +255: setchar62 ("3E) h:=3460645+509738=3970383, hh:=252 +[macro:->] +256: set1 197("C5) h:=3970383+491520=4461903, hh:=283 +258: set1 191("BF) h:=4461903+491520=4953423, hh:=314 +260: w3 218453 h:=4953423+218453=5171876, hh:=328 +[ ] +264: set1 197("C5) h:=5171876+491520=5663396, hh:=359 +266: set1 191("BF) h:=5663396+491520=6154916, hh:=390 +268: w0 218453 h:=6154916+218453=6373369, hh:=404 +[ ] +269: fntnum1 current font is min10 +270: set2 17727("453F) type=0 h:=6373369+630598=7003967, hh:=444 +[䔿] +273: pop +level 1:(h=0,v=3014656,w=0,x=0,y=786432,z=0,hh=0,vv=191) +274: y0 786432 v:=3014656+786432=3801088, vv:=241 +275: push +level 1:(h=0,v=3801088,w=0,x=0,y=786432,z=0,hh=0,vv=241) +276: push +level 2:(h=0,v=3801088,w=0,x=0,y=786432,z=0,hh=0,vv=241) +277: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +280: pop +level 2:(h=0,v=3801088,w=0,x=0,y=786432,z=0,hh=0,vv=241) +281: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +285: fntnum0 current font is ec-lmr10 +286: setchar92 ("5C) h:=630598+327680=958278, hh:=61 +287: setchar106 ("6A) h:=958278+200245=1158523, hh:=74 +288: setchar111 ("6F) h:=1158523+327680=1486203, hh:=95 +289: setchar98 ("62) h:=1486203+364085=1850288, hh:=118 +290: setchar110 ("6E) h:=1850288+364085=2214373, hh:=141 +291: setchar97 ("61) h:=2214373+327680=2542053, hh:=162 +292: setchar109 ("6D) h:=2542053+546111=3088164, hh:=197 +293: setchar101 ("65) h:=3088164+291275=3379439, hh:=215 +294: setchar46 ("2E) h:=3379439+182043=3561482, hh:=227 +[\jobname.] +295: pop +level 1:(h=0,v=3801088,w=0,x=0,y=786432,z=0,hh=0,vv=241) +296: y0 786432 v:=3801088+786432=4587520, vv:=291 +297: push +level 1:(h=0,v=4587520,w=0,x=0,y=786432,z=0,hh=0,vv=291) +298: push +level 2:(h=0,v=4587520,w=0,x=0,y=786432,z=0,hh=0,vv=291) +299: fntnum1 current font is min10 +300: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +303: pop +level 2:(h=0,v=4587520,w=0,x=0,y=786432,z=0,hh=0,vv=291) +304: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +308: fntnum0 current font is ec-lmr10 +309: setchar111 ("6F) h:=630598+327680=958278, hh:=61 +310: setchar110 ("6E) h:=958278+364085=1322363, hh:=84 +311: setchar101 ("65) h:=1322363+291275=1613638, hh:=102 +312: setchar108 ("6C) h:=1613638+182043=1795681, hh:=114 +313: setchar101 ("65) h:=1795681+291275=2086956, hh:=132 +314: setchar116 ("74) h:=2086956+254870=2341826, hh:=148 +315: setchar116 ("74) h:=2341826+254870=2596696, hh:=164 +316: setchar101 ("65) h:=2596696+291275=2887971, hh:=182 +317: setchar114 ("72) h:=2887971+256683=3144654, hh:=198 +318: setchar46 ("2E) h:=3144654+182043=3326697, hh:=210 +[oneletter.] +319: pop +level 1:(h=0,v=4587520,w=0,x=0,y=786432,z=0,hh=0,vv=291) +320: y0 786432 v:=4587520+786432=5373952, vv:=340 +321: push +level 1:(h=0,v=5373952,w=0,x=0,y=786432,z=0,hh=0,vv=340) +322: right3 1310720 h:=0+1310720=1310720, hh:=83 +326: setchar92 ("5C) h:=1310720+327680=1638400, hh:=104 +[ \] +327: set1 196("C4) h:=1638400+491520=2129920, hh:=135 +329: setchar46 ("2E) h:=2129920+182043=2311963, hh:=147 +330: setchar92 ("5C) h:=2311963+327680=2639643, hh:=168 +[.\] +331: set1 197("C5) h:=2639643+491520=3131163, hh:=199 +333: setchar46 ("2E) h:=3131163+182043=3313206, hh:=211 +334: setchar92 ("5C) h:=3313206+327680=3640886, hh:=232 +[.\] +335: set1 255("FF) h:=3640886+327680=3968566, hh:=253 +337: setchar46 ("2E) h:=3968566+182043=4150609, hh:=265 +338: right3 291271 h:=4150609+291271=4441880, hh:=281 +[. ] +342: set1 191("BF) h:=4441880+491520=4933400, hh:=312 +344: pop +level 1:(h=0,v=5373952,w=0,x=0,y=786432,z=0,hh=0,vv=340) +345: y0 786432 v:=5373952+786432=6160384, vv:=390 +346: push +level 1:(h=0,v=6160384,w=0,x=0,y=786432,z=0,hh=0,vv=390) +347: push +level 2:(h=0,v=6160384,w=0,x=0,y=786432,z=0,hh=0,vv=390) +348: fntnum1 current font is min10 +349: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +352: pop +level 2:(h=0,v=6160384,w=0,x=0,y=786432,z=0,hh=0,vv=390) +353: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +357: fntnum0 current font is ec-lmr10 +358: setchar99 ("63) h:=630598+291275=921873, hh:=58 +359: setchar115 ("73) h:=921873+258506=1180379, hh:=74 +360: setchar110 ("6E) h:=1180379+364085=1544464, hh:=97 +361: setchar97 ("61) h:=1544464+327680=1872144, hh:=118 +362: setchar109 ("6D) h:=1872144+546111=2418255, hh:=153 +363: setchar101 ("65) h:=2418255+291275=2709530, hh:=171 +364: setchar49 ("31) h:=2709530+327680=3037210, hh:=192 +365: setchar46 ("2E) h:=3037210+182043=3219253, hh:=204 +[csname1.] +366: pop +level 1:(h=0,v=6160384,w=0,x=0,y=786432,z=0,hh=0,vv=390) +367: y0 786432 v:=6160384+786432=6946816, vv:=440 +368: push +level 1:(h=0,v=6946816,w=0,x=0,y=786432,z=0,hh=0,vv=440) +369: right3 1310720 h:=0+1310720=1310720, hh:=83 +373: setchar92 ("5C) h:=1310720+327680=1638400, hh:=104 +[ \] +374: set1 197("C5) h:=1638400+491520=2129920, hh:=135 +376: set1 191("BF) h:=2129920+491520=2621440, hh:=166 +378: setchar92 ("5C) h:=2621440+327680=2949120, hh:=187 +[\] +379: set1 197("C5) h:=2949120+491520=3440640, hh:=218 +381: set1 191("BF) h:=3440640+491520=3932160, hh:=249 +383: setchar44 ("2C) h:=3932160+182043=4114203, hh:=261 +384: w3 218453 h:=4114203+218453=4332656, hh:=274 +388: setchar92 ("5C) h:=4332656+327680=4660336, hh:=295 +[, \] +389: set1 197("C5) h:=4660336+491520=5151856, hh:=326 +391: set1 191("BF) h:=5151856+491520=5643376, hh:=357 +393: setchar44 ("2C) h:=5643376+182043=5825419, hh:=369 +394: w0 218453 h:=5825419+218453=6043872, hh:=383 +395: setchar92 ("5C) h:=6043872+327680=6371552, hh:=404 +[, \] +396: fntnum1 current font is min10 +397: set2 17727("453F) type=0 h:=6371552+630598=7002150, hh:=444 +[䔿] +400: pop +level 1:(h=0,v=6946816,w=0,x=0,y=786432,z=0,hh=0,vv=440) +401: y0 786432 v:=6946816+786432=7733248, vv:=490 +402: push +level 1:(h=0,v=7733248,w=0,x=0,y=786432,z=0,hh=0,vv=490) +403: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +407: fntnum0 current font is ec-lmr10 +408: setchar92 ("5C) h:=1310720+327680=1638400, hh:=104 +[\] +409: fntnum1 current font is min10 +410: set2 9250("2422) type=0 h:=1638400+630598=2268998, hh:=144 +[␢] +413: fntnum0 current font is ec-lmr10 +414: setchar61 ("3D) h:=2268998+509738=2778736, hh:=176 +415: setchar62 ("3E) h:=2778736+509738=3288474, hh:=208 +416: right3 218453 h:=3288474+218453=3506927, hh:=222 +420: setchar104 ("68) h:=3506927+364085=3871012, hh:=245 +421: setchar111 ("6F) h:=3871012+327680=4198692, hh:=266 +422: setchar103 ("67) h:=4198692+327680=4526372, hh:=287 +423: setchar101 ("65) h:=4526372+291275=4817647, hh:=305 +424: setchar44 ("2C) h:=4817647+182043=4999690, hh:=317 +[=> hoge,] +425: pop +level 1:(h=0,v=7733248,w=0,x=0,y=786432,z=0,hh=0,vv=490) +426: y0 786432 v:=7733248+786432=8519680, vv:=540 +427: push +level 1:(h=0,v=8519680,w=0,x=0,y=786432,z=0,hh=0,vv=540) +428: right3 1310720 h:=0+1310720=1310720, hh:=83 +432: setchar92 ("5C) h:=1310720+327680=1638400, hh:=104 +[ \] +433: set1 227("E3) h:=1638400+327680=1966080, hh:=125 +435: set1 129("81) h:=1966080+491520=2457600, hh:=156 +437: w2 -18205 h:=2457600-18205=2439395, hh:=155 +440: set1 130("82) h:=2439395+473301=2912696, hh:=185 +442: setchar61 ("3D) h:=2912696+509738=3422434, hh:=217 +443: setchar62 ("3E) h:=3422434+509738=3932172, hh:=249 +444: right3 218453 h:=3932172+218453=4150625, hh:=263 +448: setchar112 ("70) h:=4150625+364085=4514710, hh:=286 +449: setchar105 ("69) h:=4514710+182043=4696753, hh:=298 +450: setchar121 ("79) h:=4696753+345898=5042651, hh:=320 +451: w0 -18205 h:=5042651-18205=5024446, hh:=319 +452: setchar111 ("6F) h:=5024446+327680=5352126, hh:=340 +453: setchar44 ("2C) h:=5352126+182043=5534169, hh:=352 +[=> piyo,] +454: pop +level 1:(h=0,v=8519680,w=0,x=0,y=786432,z=0,hh=0,vv=540) +455: y0 786432 v:=8519680+786432=9306112, vv:=589 +456: push +level 1:(h=0,v=9306112,w=0,x=0,y=786432,z=0,hh=0,vv=589) +457: right3 1310720 h:=0+1310720=1310720, hh:=83 +461: setchar92 ("5C) h:=1310720+327680=1638400, hh:=104 +[ \] +462: set1 227("E3) h:=1638400+327680=1966080, hh:=125 +464: set1 129("81) h:=1966080+491520=2457600, hh:=156 +466: w2 -18205 h:=2457600-18205=2439395, hh:=155 +469: set1 130("82) h:=2439395+473301=2912696, hh:=185 +471: setchar61 ("3D) h:=2912696+509738=3422434, hh:=217 +472: setchar62 ("3E) h:=3422434+509738=3932172, hh:=249 +473: right3 218453 h:=3932172+218453=4150625, hh:=263 +477: setchar112 ("70) h:=4150625+364085=4514710, hh:=286 +478: setchar105 ("69) h:=4514710+182043=4696753, hh:=298 +479: setchar121 ("79) h:=4696753+345898=5042651, hh:=320 +480: w0 -18205 h:=5042651-18205=5024446, hh:=319 +481: setchar111 ("6F) h:=5024446+327680=5352126, hh:=340 +482: setchar46 ("2E) h:=5352126+182043=5534169, hh:=352 +[=> piyo.] +483: pop +level 1:(h=0,v=9306112,w=0,x=0,y=786432,z=0,hh=0,vv=589) +484: y0 786432 v:=9306112+786432=10092544, vv:=639 +485: push +level 1:(h=0,v=10092544,w=0,x=0,y=786432,z=0,hh=0,vv=639) +486: push +level 2:(h=0,v=10092544,w=0,x=0,y=786432,z=0,hh=0,vv=639) +487: fntnum1 current font is min10 +488: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +491: pop +level 2:(h=0,v=10092544,w=0,x=0,y=786432,z=0,hh=0,vv=639) +492: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +496: fntnum0 current font is ec-lmr10 +497: setchar48 ("30) h:=630598+327680=958278, hh:=61 +498: setchar120 ("78) h:=958278+345898=1304176, hh:=83 +499: setchar70 ("46) h:=1304176+427818=1731994, hh:=110 +500: setchar70 ("46) h:=1731994+427818=2159812, hh:=137 +501: setchar46 ("2E) h:=2159812+182043=2341855, hh:=149 +[0xFF.] +502: pop +level 1:(h=0,v=10092544,w=0,x=0,y=786432,z=0,hh=0,vv=639) +503: y0 786432 v:=10092544+786432=10878976, vv:=689 +504: push +level 1:(h=0,v=10878976,w=0,x=0,y=786432,z=0,hh=0,vv=689) +505: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +509: fntnum1 current font is min10 +510: set2 9250("2422) type=0 h:=1310720+630598=1941318, hh:=123 +[␢] +513: fntnum0 current font is ec-lmr10 +514: setchar44 ("2C) h:=1941318+182043=2123361, hh:=135 +515: w3 218453 h:=2123361+218453=2341814, hh:=148 +519: setchar40 ("28) h:=2341814+254870=2596684, hh:=164 +520: setchar92 ("5C) h:=2596684+327680=2924364, hh:=185 +[, (\] +521: set1 255("FF) h:=2924364+327680=3252044, hh:=206 +523: set1 197("C5) h:=3252044+491520=3743564, hh:=237 +525: set1 255("FF) h:=3743564+327680=4071244, hh:=258 +527: set1 191("BF) h:=4071244+491520=4562764, hh:=289 +529: setchar58 ("3A) h:=4562764+182043=4744807, hh:=301 +530: setchar109 ("6D) h:=4744807+546111=5290918, hh:=336 +531: setchar97 ("61) h:=5290918+327680=5618598, hh:=357 +532: setchar99 ("63) h:=5618598+291275=5909873, hh:=375 +533: setchar114 ("72) h:=5909873+256683=6166556, hh:=391 +534: setchar111 ("6F) h:=6166556+327680=6494236, hh:=412 +535: setchar58 ("3A) h:=6494236+182043=6676279, hh:=424 +536: setchar45 ("2D) h:=6676279+218453=6894732, hh:=438 +537: setchar62 ("3E) h:=6894732+509738=7404470, hh:=470 +[:macro:->] +538: fntnum1 current font is min10 +539: set2 9250("2422) type=0 h:=7404470+630598=8035068, hh:=510 +[␢] +542: fntnum0 current font is ec-lmr10 +543: setchar41 ("29) h:=8035068+254870=8289938, hh:=526 +544: setchar44 ("2C) h:=8289938+182043=8471981, hh:=538 +545: w0 218453 h:=8471981+218453=8690434, hh:=550 +546: setchar92 ("5C) h:=8690434+327680=9018114, hh:=571 +[), \] +547: set1 255("FF) h:=9018114+327680=9345794, hh:=592 +549: set1 197("C5) h:=9345794+491520=9837314, hh:=623 +551: set1 255("FF) h:=9837314+327680=10164994, hh:=644 +553: set1 191("BF) h:=10164994+491520=10656514, hh:=675 +555: setchar44 ("2C) h:=10656514+182043=10838557, hh:=687 +556: w0 218453 h:=10838557+218453=11057010, hh:=700 +557: setchar109 ("6D) h:=11057010+546111=11603121, hh:=735 +558: setchar97 ("61) h:=11603121+327680=11930801, hh:=756 +559: setchar99 ("63) h:=11930801+291275=12222076, hh:=774 +560: setchar114 ("72) h:=12222076+256683=12478759, hh:=790 +561: setchar111 ("6F) h:=12478759+327680=12806439, hh:=811 +562: setchar58 ("3A) h:=12806439+182043=12988482, hh:=823 +563: setchar45 ("2D) h:=12988482+218453=13206935, hh:=837 +564: setchar62 ("3E) h:=13206935+509738=13716673, hh:=869 +565: setchar40 ("28) h:=13716673+254870=13971543, hh:=885 +566: setchar92 ("5C) h:=13971543+327680=14299223, hh:=906 +[, macro:->(\] +567: set1 255("FF) h:=14299223+327680=14626903, hh:=927 +569: set1 197("C5) h:=14626903+491520=15118423, hh:=958 +571: set1 255("FF) h:=15118423+327680=15446103, hh:=979 +573: set1 191("BF) h:=15446103+491520=15937623, hh:=1010 +575: setchar58 ("3A) h:=15937623+182043=16119666, hh:=1022 +576: setchar109 ("6D) h:=16119666+546111=16665777, hh:=1057 +577: setchar97 ("61) h:=16665777+327680=16993457, hh:=1078 +578: setchar99 ("63) h:=16993457+291275=17284732, hh:=1096 +579: setchar114 ("72) h:=17284732+256683=17541415, hh:=1112 +580: setchar111 ("6F) h:=17541415+327680=17869095, hh:=1133 +581: setchar58 ("3A) h:=17869095+182043=18051138, hh:=1145 +582: setchar45 ("2D) h:=18051138+218453=18269591, hh:=1159 +583: setchar62 ("3E) h:=18269591+509738=18779329, hh:=1191 +[:macro:->] +584: fntnum1 current font is min10 +585: set2 9250("2422) type=0 h:=18779329+630598=19409927, hh:=1231 +[␢] +588: fntnum0 current font is ec-lmr10 +589: setchar41 ("29) h:=19409927+254870=19664797, hh:=1247 +590: setchar46 ("2E) h:=19664797+182043=19846840, hh:=1259 +[).] +591: pop +level 1:(h=0,v=10878976,w=0,x=0,y=786432,z=0,hh=0,vv=689) +592: y0 786432 v:=10878976+786432=11665408, vv:=739 +593: push +level 1:(h=0,v=11665408,w=0,x=0,y=786432,z=0,hh=0,vv=739) +594: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +598: fntnum1 current font is min10 +599: set2 9252("2424) type=0 h:=1310720+630598=1941318, hh:=123 +[␤] +602: fntnum0 current font is ec-lmr10 +603: setchar44 ("2C) h:=1941318+182043=2123361, hh:=135 +604: w3 218453 h:=2123361+218453=2341814, hh:=148 +608: setchar40 ("28) h:=2341814+254870=2596684, hh:=164 +609: setchar92 ("5C) h:=2596684+327680=2924364, hh:=185 +[, (\] +610: set1 255("FF) h:=2924364+327680=3252044, hh:=206 +612: setchar58 ("3A) h:=3252044+182043=3434087, hh:=218 +613: setchar109 ("6D) h:=3434087+546111=3980198, hh:=253 +614: setchar97 ("61) h:=3980198+327680=4307878, hh:=274 +615: setchar99 ("63) h:=4307878+291275=4599153, hh:=292 +616: setchar114 ("72) h:=4599153+256683=4855836, hh:=308 +617: setchar111 ("6F) h:=4855836+327680=5183516, hh:=329 +618: setchar58 ("3A) h:=5183516+182043=5365559, hh:=341 +619: setchar45 ("2D) h:=5365559+218453=5584012, hh:=355 +620: setchar62 ("3E) h:=5584012+509738=6093750, hh:=387 +[:macro:->] +621: fntnum1 current font is min10 +622: set2 9252("2424) type=0 h:=6093750+630598=6724348, hh:=427 +[␤] +625: fntnum0 current font is ec-lmr10 +626: setchar41 ("29) h:=6724348+254870=6979218, hh:=443 +627: setchar44 ("2C) h:=6979218+182043=7161261, hh:=455 +628: w0 218453 h:=7161261+218453=7379714, hh:=467 +629: setchar92 ("5C) h:=7379714+327680=7707394, hh:=488 +[), \] +630: set1 255("FF) h:=7707394+327680=8035074, hh:=509 +632: setchar44 ("2C) h:=8035074+182043=8217117, hh:=521 +633: w0 218453 h:=8217117+218453=8435570, hh:=534 +634: setchar109 ("6D) h:=8435570+546111=8981681, hh:=569 +635: setchar97 ("61) h:=8981681+327680=9309361, hh:=590 +636: setchar99 ("63) h:=9309361+291275=9600636, hh:=608 +637: setchar114 ("72) h:=9600636+256683=9857319, hh:=624 +638: setchar111 ("6F) h:=9857319+327680=10184999, hh:=645 +639: setchar58 ("3A) h:=10184999+182043=10367042, hh:=657 +640: setchar45 ("2D) h:=10367042+218453=10585495, hh:=671 +641: setchar62 ("3E) h:=10585495+509738=11095233, hh:=703 +642: setchar40 ("28) h:=11095233+254870=11350103, hh:=719 +643: setchar92 ("5C) h:=11350103+327680=11677783, hh:=740 +[, macro:->(\] +644: set1 255("FF) h:=11677783+327680=12005463, hh:=761 +646: setchar58 ("3A) h:=12005463+182043=12187506, hh:=773 +647: setchar109 ("6D) h:=12187506+546111=12733617, hh:=808 +648: setchar97 ("61) h:=12733617+327680=13061297, hh:=829 +649: setchar99 ("63) h:=13061297+291275=13352572, hh:=847 +650: setchar114 ("72) h:=13352572+256683=13609255, hh:=863 +651: setchar111 ("6F) h:=13609255+327680=13936935, hh:=884 +652: setchar58 ("3A) h:=13936935+182043=14118978, hh:=896 +653: setchar45 ("2D) h:=14118978+218453=14337431, hh:=910 +654: setchar62 ("3E) h:=14337431+509738=14847169, hh:=942 +[:macro:->] +655: fntnum1 current font is min10 +656: set2 9252("2424) type=0 h:=14847169+630598=15477767, hh:=982 +[␤] +659: fntnum0 current font is ec-lmr10 +660: setchar41 ("29) h:=15477767+254870=15732637, hh:=998 +661: setchar46 ("2E) h:=15732637+182043=15914680, hh:=1010 +[).] +662: pop +level 1:(h=0,v=11665408,w=0,x=0,y=786432,z=0,hh=0,vv=739) +663: y0 786432 v:=11665408+786432=12451840, vv:=789 +664: push +level 1:(h=0,v=12451840,w=0,x=0,y=786432,z=0,hh=0,vv=789) +665: push +level 2:(h=0,v=12451840,w=0,x=0,y=786432,z=0,hh=0,vv=789) +666: fntnum1 current font is min10 +667: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +670: pop +level 2:(h=0,v=12451840,w=0,x=0,y=786432,z=0,hh=0,vv=789) +671: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +675: fntnum0 current font is ec-lmr10 +676: setchar99 ("63) h:=630598+291275=921873, hh:=58 +677: setchar111 ("6F) h:=921873+327680=1249553, hh:=79 +678: setchar110 ("6E) h:=1249553+364085=1613638, hh:=102 +679: right2 -18205 h:=1613638-18205=1595433, hh:=101 +682: setchar116 ("74) h:=1595433+254870=1850303, hh:=117 +683: setchar101 ("65) h:=1850303+291275=2141578, hh:=135 +684: setchar120 ("78) h:=2141578+345898=2487476, hh:=157 +685: setchar116 ("74) h:=2487476+254870=2742346, hh:=173 +686: setchar115 ("73) h:=2742346+258506=3000852, hh:=189 +687: setchar46 ("2E) h:=3000852+182043=3182895, hh:=201 +[contexts.] +688: pop +level 1:(h=0,v=12451840,w=0,x=0,y=786432,z=0,hh=0,vv=789) +689: y0 786432 v:=12451840+786432=13238272, vv:=839 +690: push +level 1:(h=0,v=13238272,w=0,x=0,y=786432,z=0,hh=0,vv=839) +691: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +695: fntnum1 current font is min10 +696: set2 9250("2422) type=0 h:=1310720+630598=1941318, hh:=123 +[␢] +699: fntnum0 current font is ec-lmr10 +700: set1 197("C5) h:=1941318+491520=2432838, hh:=154 +702: set1 191("BF) h:=2432838+491520=2924358, hh:=185 +704: w3 218453 h:=2924358+218453=3142811, hh:=199 +708: setchar97 ("61) h:=3142811+327680=3470491, hh:=220 +[ a] +709: set1 197("C5) h:=3470491+491520=3962011, hh:=251 +711: set1 191("BF) h:=3962011+491520=4453531, hh:=282 +713: w0 218453 h:=4453531+218453=4671984, hh:=296 +[ ] +714: set1 197("C5) h:=4671984+491520=5163504, hh:=327 +716: set1 191("BF) h:=5163504+491520=5655024, hh:=358 +718: w0 218453 h:=5655024+218453=5873477, hh:=372 +[ ] +719: fntnum1 current font is min10 +720: set2 17727("453F) type=0 h:=5873477+630598=6504075, hh:=412 +723: w0 218453 h:=6504075+218453=6722528, hh:=426 +[䔿 ] +724: fntnum0 current font is ec-lmr10 +725: set1 197("C5) h:=6722528+491520=7214048, hh:=457 +727: set1 191("BF) h:=7214048+491520=7705568, hh:=488 +729: w0 218453 h:=7705568+218453=7924021, hh:=502 +[ ] +730: set1 197("C5) h:=7924021+491520=8415541, hh:=533 +732: set1 191("BF) h:=8415541+491520=8907061, hh:=564 +734: w0 218453 h:=8907061+218453=9125514, hh:=578 +[ ] +735: fntnum1 current font is min10 +736: set2 17727("453F) type=0 h:=9125514+630598=9756112, hh:=618 +739: x3 436906 h:=9756112+436906=10193018, hh:=646 +[䔿 ] +743: fntnum0 current font is ec-lmr10 +744: set1 197("C5) h:=10193018+491520=10684538, hh:=677 +746: set1 191("BF) h:=10684538+491520=11176058, hh:=708 +748: w0 218453 h:=11176058+218453=11394511, hh:=722 +[ ] +749: fntnum1 current font is min10 +750: set2 17727("453F) type=0 h:=11394511+630598=12025109, hh:=762 +753: x0 436906 h:=12025109+436906=12462015, hh:=789 +754: set2 9252("2424) type=0 h:=12462015+630598=13092613, hh:=829 +[䔿 ␤] +757: fntnum0 current font is ec-lmr10 +758: setchar109 ("6D) h:=13092613+546111=13638724, hh:=864 +759: setchar97 ("61) h:=13638724+327680=13966404, hh:=885 +760: setchar99 ("63) h:=13966404+291275=14257679, hh:=903 +761: setchar114 ("72) h:=14257679+256683=14514362, hh:=919 +762: setchar111 ("6F) h:=14514362+327680=14842042, hh:=940 +763: setchar58 ("3A) h:=14842042+182043=15024085, hh:=952 +764: setchar45 ("2D) h:=15024085+218453=15242538, hh:=966 +765: setchar62 ("3E) h:=15242538+509738=15752276, hh:=998 +[macro:->] +766: set1 197("C5) h:=15752276+491520=16243796, hh:=1029 +768: set1 191("BF) h:=16243796+491520=16735316, hh:=1060 +770: w0 218453 h:=16735316+218453=16953769, hh:=1074 +[ ] +771: set1 197("C5) h:=16953769+491520=17445289, hh:=1105 +773: set1 191("BF) h:=17445289+491520=17936809, hh:=1136 +775: w0 218453 h:=17936809+218453=18155262, hh:=1150 +[ ] +776: fntnum1 current font is min10 +777: set2 17727("453F) type=0 h:=18155262+630598=18785860, hh:=1190 +[䔿] +780: pop +level 1:(h=0,v=13238272,w=0,x=0,y=786432,z=0,hh=0,vv=839) +781: y0 786432 v:=13238272+786432=14024704, vv:=888 +782: push +level 1:(h=0,v=14024704,w=0,x=0,y=786432,z=0,hh=0,vv=888) +783: right3 1310720 h:=0+1310720=1310720, hh:=83 +787: set2 9250("2422) type=0 h:=1310720+630598=1941318, hh:=123 +[ ␢] +790: fntnum0 current font is ec-lmr10 +791: set1 197("C5) h:=1941318+491520=2432838, hh:=154 +793: set1 191("BF) h:=2432838+491520=2924358, hh:=185 +795: w3 218453 h:=2924358+218453=3142811, hh:=199 +[ ] +799: set1 197("C5) h:=3142811+491520=3634331, hh:=230 +801: set1 191("BF) h:=3634331+491520=4125851, hh:=261 +803: fntnum1 current font is min10 +804: set2 17727("453F) type=0 h:=4125851+630598=4756449, hh:=301 +[䔿] +807: fntnum0 current font is ec-lmr10 +808: set1 197("C5) h:=4756449+491520=5247969, hh:=332 +810: set1 191("BF) h:=5247969+491520=5739489, hh:=363 +812: w0 218453 h:=5739489+218453=5957942, hh:=377 +813: setchar97 ("61) h:=5957942+327680=6285622, hh:=398 +[ a] +814: set1 197("C5) h:=6285622+491520=6777142, hh:=429 +816: set1 191("BF) h:=6777142+491520=7268662, hh:=460 +818: w0 218453 h:=7268662+218453=7487115, hh:=474 +[ ] +819: set1 197("C5) h:=7487115+491520=7978635, hh:=505 +821: set1 191("BF) h:=7978635+491520=8470155, hh:=536 +823: w0 218453 h:=8470155+218453=8688608, hh:=550 +[ ] +824: fntnum1 current font is min10 +825: set2 17727("453F) type=0 h:=8688608+630598=9319206, hh:=590 +828: w0 218453 h:=9319206+218453=9537659, hh:=604 +[䔿 ] +829: fntnum0 current font is ec-lmr10 +830: set1 197("C5) h:=9537659+491520=10029179, hh:=635 +832: set1 191("BF) h:=10029179+491520=10520699, hh:=666 +834: w0 218453 h:=10520699+218453=10739152, hh:=680 +[ ] +835: set1 197("C5) h:=10739152+491520=11230672, hh:=711 +837: set1 191("BF) h:=11230672+491520=11722192, hh:=742 +839: w0 218453 h:=11722192+218453=11940645, hh:=756 +[ ] +840: fntnum1 current font is min10 +841: set2 17727("453F) type=0 h:=11940645+630598=12571243, hh:=796 +844: right3 436906 h:=12571243+436906=13008149, hh:=824 +[䔿 ] +848: fntnum0 current font is ec-lmr10 +849: set1 197("C5) h:=13008149+491520=13499669, hh:=855 +851: set1 191("BF) h:=13499669+491520=13991189, hh:=886 +853: w0 218453 h:=13991189+218453=14209642, hh:=900 +[ ] +854: fntnum1 current font is min10 +855: set2 17727("453F) type=0 h:=14209642+630598=14840240, hh:=940 +858: w0 218453 h:=14840240+218453=15058693, hh:=954 +859: set2 9252("2424) type=0 h:=15058693+630598=15689291, hh:=994 +[䔿 ␤] +862: fntnum0 current font is ec-lmr10 +863: set1 255("FF) h:=15689291+327680=16016971, hh:=1015 +865: pop +level 1:(h=0,v=14024704,w=0,x=0,y=786432,z=0,hh=0,vv=888) +866: y0 786432 v:=14024704+786432=14811136, vv:=938 +867: push +level 1:(h=0,v=14811136,w=0,x=0,y=786432,z=0,hh=0,vv=938) +868: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +872: fntnum1 current font is min10 +873: set2 9252("2424) type=0 h:=1310720+630598=1941318, hh:=123 +[␤] +876: pop +level 1:(h=0,v=14811136,w=0,x=0,y=786432,z=0,hh=0,vv=938) +877: y0 786432 v:=14811136+786432=15597568, vv:=988 +878: push +level 1:(h=0,v=15597568,w=0,x=0,y=786432,z=0,hh=0,vv=988) +879: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +883: fntnum0 current font is ec-lmr10 +884: setchar46 ("2E) h:=1310720+182043=1492763, hh:=95 +885: setchar97 ("61) h:=1492763+327680=1820443, hh:=116 +886: setchar46 ("2E) h:=1820443+182043=2002486, hh:=128 +887: setchar46 ("2E) h:=2002486+182043=2184529, hh:=140 +888: setchar46 ("2E) h:=2184529+182043=2366572, hh:=152 +889: setchar99 ("63) h:=2366572+291275=2657847, hh:=170 +890: setchar46 ("2E) h:=2657847+182043=2839890, hh:=182 +891: setchar98 ("62) h:=2839890+364085=3203975, hh:=205 +892: setchar46 ("2E) h:=3203975+182043=3386018, hh:=216 +893: setchar46 ("2E) h:=3386018+182043=3568061, hh:=228 +[.a...c.b..] +894: pop +level 1:(h=0,v=15597568,w=0,x=0,y=786432,z=0,hh=0,vv=988) +895: y0 786432 v:=15597568+786432=16384000, vv:=1038 +896: push +level 1:(h=0,v=16384000,w=0,x=0,y=786432,z=0,hh=0,vv=1038) +897: right3 1310720 h:=0+1310720=1310720, hh:=83 +901: setchar46 ("2E) h:=1310720+182043=1492763, hh:=95 +902: setchar97 ("61) h:=1492763+327680=1820443, hh:=116 +903: setchar46 ("2E) h:=1820443+182043=2002486, hh:=128 +904: setchar46 ("2E) h:=2002486+182043=2184529, hh:=140 +905: setchar46 ("2E) h:=2184529+182043=2366572, hh:=152 +906: setchar99 ("63) h:=2366572+291275=2657847, hh:=170 +907: setchar46 ("2E) h:=2657847+182043=2839890, hh:=182 +908: setchar98 ("62) h:=2839890+364085=3203975, hh:=205 +909: setchar46 ("2E) h:=3203975+182043=3386018, hh:=216 +910: setchar46 ("2E) h:=3386018+182043=3568061, hh:=228 +[ .a...c.b..] +911: pop +level 1:(h=0,v=16384000,w=0,x=0,y=786432,z=0,hh=0,vv=1038) +912: y0 786432 v:=16384000+786432=17170432, vv:=1088 +913: push +level 1:(h=0,v=17170432,w=0,x=0,y=786432,z=0,hh=0,vv=1088) +914: push +level 2:(h=0,v=17170432,w=0,x=0,y=786432,z=0,hh=0,vv=1088) +915: fntnum1 current font is min10 +916: set2 8739("2223) type=0 h:=0+630598=630598, hh:=40 +[∣] +919: pop +level 2:(h=0,v=17170432,w=0,x=0,y=786432,z=0,hh=0,vv=1088) +920: right3 630598 h:=0+630598=630598, hh:=40 +[ ] +924: fntnum0 current font is ec-lmr10 +925: setchar99 ("63) h:=630598+291275=921873, hh:=58 +926: setchar115 ("73) h:=921873+258506=1180379, hh:=74 +927: setchar110 ("6E) h:=1180379+364085=1544464, hh:=97 +928: setchar97 ("61) h:=1544464+327680=1872144, hh:=118 +929: setchar109 ("6D) h:=1872144+546111=2418255, hh:=153 +930: setchar101 ("65) h:=2418255+291275=2709530, hh:=171 +931: setchar50 ("32) h:=2709530+327680=3037210, hh:=192 +932: setchar46 ("2E) h:=3037210+182043=3219253, hh:=204 +[csname2.] +933: pop +level 1:(h=0,v=17170432,w=0,x=0,y=786432,z=0,hh=0,vv=1088) +934: y0 786432 v:=17170432+786432=17956864, vv:=1137 +935: push +level 1:(h=0,v=17956864,w=0,x=0,y=786432,z=0,hh=0,vv=1137) +936: right3 1310720 h:=0+1310720=1310720, hh:=83 +940: setchar83 ("53) h:=1310720+364085=1674805, hh:=106 +941: setchar72 ("48) h:=1674805+491520=2166325, hh:=137 +942: setchar79 ("4F) h:=2166325+509738=2676063, hh:=169 +943: right2 -18205 h:=2676063-18205=2657858, hh:=168 +946: setchar87 ("57) h:=2657858+673578=3331436, hh:=211 +947: right3 218453 h:=3331436+218453=3549889, hh:=225 +951: setchar46 ("2E) h:=3549889+182043=3731932, hh:=237 +952: setchar46 ("2E) h:=3731932+182043=3913975, hh:=249 +953: setchar46 ("2E) h:=3913975+182043=4096018, hh:=261 +[ SHOW ...] +954: pop +level 1:(h=0,v=17956864,w=0,x=0,y=786432,z=0,hh=0,vv=1137) +955: y0 786432 v:=17956864+786432=18743296, vv:=1187 +956: push +level 1:(h=0,v=18743296,w=0,x=0,y=786432,z=0,hh=0,vv=1187) +957: right3 1310720 h:=0+1310720=1310720, hh:=83 +961: setchar83 ("53) h:=1310720+364085=1674805, hh:=106 +962: setchar84 ("54) h:=1674805+473301=2148106, hh:=136 +963: setchar82 ("52) h:=2148106+482410=2630516, hh:=167 +964: setchar73 ("49) h:=2630516+236650=2867166, hh:=182 +965: setchar78 ("4E) h:=2867166+491520=3358686, hh:=213 +966: setchar71 ("47) h:=3358686+514261=3872947, hh:=246 +967: right3 218453 h:=3872947+218453=4091400, hh:=259 +971: setchar92 ("5C) h:=4091400+327680=4419080, hh:=280 +[ STRING \] +972: set1 197("C5) h:=4419080+491520=4910600, hh:=311 +974: set1 191("BF) h:=4910600+491520=5402120, hh:=342 +976: setchar46 ("2E) h:=5402120+182043=5584163, hh:=354 +977: setchar92 ("5C) h:=5584163+327680=5911843, hh:=375 +[.\] +978: fntnum1 current font is min10 +979: set2 17727("453F) type=0 h:=5911843+630598=6542441, hh:=415 +[䔿] +982: fntnum0 current font is ec-lmr10 +983: setchar46 ("2E) h:=6542441+182043=6724484, hh:=427 +984: setchar92 ("5C) h:=6724484+327680=7052164, hh:=448 +[.\] +985: set1 197("C5) h:=7052164+491520=7543684, hh:=479 +987: set1 191("BF) h:=7543684+491520=8035204, hh:=510 +989: setchar46 ("2E) h:=8035204+182043=8217247, hh:=522 +990: setchar92 ("5C) h:=8217247+327680=8544927, hh:=543 +[.\] +991: fntnum1 current font is min10 +992: set2 17727("453F) type=0 h:=8544927+630598=9175525, hh:=583 +[䔿] +995: pop +level 1:(h=0,v=18743296,w=0,x=0,y=786432,z=0,hh=0,vv=1187) +996: y0 786432 v:=18743296+786432=19529728, vv:=1237 +997: push +level 1:(h=0,v=19529728,w=0,x=0,y=786432,z=0,hh=0,vv=1237) +998: right3 1310720 h:=0+1310720=1310720, hh:=83 +[ ] +1002: fntnum0 current font is ec-lmr10 +1003: setchar77 ("4D) h:=1310720+600768=1911488, hh:=121 +1004: setchar69 ("45) h:=1911488+446005=2357493, hh:=149 +1005: setchar65 ("41) h:=2357493+491520=2849013, hh:=180 +1006: setchar78 ("4E) h:=2849013+491520=3340533, hh:=211 +1007: setchar73 ("49) h:=3340533+236650=3577183, hh:=226 +1008: setchar78 ("4E) h:=3577183+491520=4068703, hh:=257 +1009: setchar71 ("47) h:=4068703+514261=4582964, hh:=290 +1010: right3 218453 h:=4582964+218453=4801417, hh:=304 +1014: setchar109 ("6D) h:=4801417+546111=5347528, hh:=339 +1015: setchar97 ("61) h:=5347528+327680=5675208, hh:=360 +1016: setchar99 ("63) h:=5675208+291275=5966483, hh:=378 +1017: setchar114 ("72) h:=5966483+256683=6223166, hh:=394 +1018: setchar111 ("6F) h:=6223166+327680=6550846, hh:=415 +1019: setchar58 ("3A) h:=6550846+182043=6732889, hh:=427 +1020: setchar45 ("2D) h:=6732889+218453=6951342, hh:=441 +1021: setchar62 ("3E) h:=6951342+509738=7461080, hh:=473 +1022: setchar97 ("61) h:=7461080+327680=7788760, hh:=494 +1023: setchar46 ("2E) h:=7788760+182043=7970803, hh:=506 +1024: setchar109 ("6D) h:=7970803+546111=8516914, hh:=541 +1025: setchar97 ("61) h:=8516914+327680=8844594, hh:=562 +1026: setchar99 ("63) h:=8844594+291275=9135869, hh:=580 +1027: setchar114 ("72) h:=9135869+256683=9392552, hh:=596 +1028: setchar111 ("6F) h:=9392552+327680=9720232, hh:=617 +1029: setchar58 ("3A) h:=9720232+182043=9902275, hh:=629 +1030: setchar45 ("2D) h:=9902275+218453=10120728, hh:=643 +1031: setchar62 ("3E) h:=10120728+509738=10630466, hh:=675 +1032: setchar98 ("62) h:=10630466+364085=10994551, hh:=698 +1033: setchar46 ("2E) h:=10994551+182043=11176594, hh:=710 +1034: setchar109 ("6D) h:=11176594+546111=11722705, hh:=745 +1035: setchar97 ("61) h:=11722705+327680=12050385, hh:=765 +1036: setchar99 ("63) h:=12050385+291275=12341660, hh:=783 +1037: setchar114 ("72) h:=12341660+256683=12598343, hh:=799 +1038: setchar111 ("6F) h:=12598343+327680=12926023, hh:=820 +1039: setchar58 ("3A) h:=12926023+182043=13108066, hh:=832 +1040: setchar45 ("2D) h:=13108066+218453=13326519, hh:=846 +1041: setchar62 ("3E) h:=13326519+509738=13836257, hh:=878 +1042: setchar97 ("61) h:=13836257+327680=14163937, hh:=899 +1043: setchar46 ("2E) h:=14163937+182043=14345980, hh:=911 +1044: setchar109 ("6D) h:=14345980+546111=14892091, hh:=945 +1045: setchar97 ("61) h:=14892091+327680=15219771, hh:=966 +1046: setchar99 ("63) h:=15219771+291275=15511046, hh:=984 +1047: setchar114 ("72) h:=15511046+256683=15767729, hh:=1000 +1048: setchar111 ("6F) h:=15767729+327680=16095409, hh:=1021 +1049: setchar58 ("3A) h:=16095409+182043=16277452, hh:=1033 +1050: setchar45 ("2D) h:=16277452+218453=16495905, hh:=1047 +1051: setchar62 ("3E) h:=16495905+509738=17005643, hh:=1079 +1052: setchar98 ("62) h:=17005643+364085=17369728, hh:=1102 +1053: setchar46 ("2E) h:=17369728+182043=17551771, hh:=1114 +[MEANING macro:->a.macro:->b.macro:->a.macro:->b.] +1054: pop +level 1:(h=0,v=19529728,w=0,x=0,y=786432,z=0,hh=0,vv=1237) +1055: pop +level 0:(h=0,v=42152922,w=0,x=0,y=0,z=0,hh=0,vv=2670) +1056: down3 1572864 v:=42152922+1572864=43725786, vv:=2770 +1060: eop diff --git a/source/texk/web2c/ptexdir/tests/pknj-e.log b/source/texk/web2c/ptexdir/tests/pknj-e.log new file mode 100644 index 000000000..4f42dab30 --- /dev/null +++ b/source/texk/web2c/ptexdir/tests/pknj-e.log @@ -0,0 +1,223 @@ + restricted \write18 enabled. + %&-line parsing enabled. +**printkanji +(./printkanji.tex +\openout1 = `p-pknj-e.out'. + + +{MSG ^^c5^^bf ^^c5^^bf 顛 } +{TOT ^^c5^^bf ^^c5^^bf 顛 } +> \A=macro: +->^^c5^^bf ^^c5^^bf 顛 . +l.29 \show\A + + +■\meaning. {MSG macro:->macro:->^^c5^^bf ^^c5^^bf 顛 } +{TOT macro:->macro:->^^c5^^bf ^^c5^^bf 顛 } +> \B=macro: +->macro:->^^c5^^bf ^^c5^^bf 顛 . +l.40 \show\B + + +■\jobname. {MSG *あ*p-pknj-e*:p-pknj-e:*macro:->:p-pknj-e:*} +{TOT *あ*p-pknj-e*:p-pknj-e:*macro:->:p-pknj-e:*} + +■oneletter. {MSG \catcode`\^^c5= 197} +{TOT \catcode`\^^c5= 197} +{MSG \catcode`^^c5 = 197} +{TOT \catcode`^^c5 = 197} +{MSG \catcode`^^c5^^bf = 197} +{TOT \catcode`^^c5^^bf = 197} +{MSG \catcode`顛 = 50623} +{TOT \catcode`顛 = 50623} +■csname1. +> \顛=macro: +->hoge. +l.72 \show\顛 + + +> \^^c5^^bf=macro: +->piyo. +l.73 \show\^^c5^^bf + + +> \^^c5^^bf=macro: +->piyo. + \^^c5^^bf + +l.74 \expandafter\show\csname ^^c5^^bf\endcsname + + +{MSG \顛=>macro:->hoge} +{TOT \顛=>macro:->hoge} +{MSG \^^c5^^bf=>macro:->piyo} +{TOT \^^c5^^bf=>macro:->piyo} +{MSG \^^c5^^bf=>macro:->piyo} +{TOT \^^c5^^bf=>macro:->piyo} +{MSG \^^c5^^bf, \^^c5^^bf, \^^c5^^bf, \顛.} +{TOT \^^c5^^bf, \^^c5^^bf, \^^c5^^bf, \顛.} + +{MSG \あ=> hoge, \^^a4^^a2=> piyo. \^^a4^^a2=> piyo. } +{TOT \あ=> hoge, \^^a4^^a2=> piyo. \^^a4^^a2=> piyo. } +■0xFF. +{MSG あ, ^^c5^^bf ^^c5^^bf 顛 , \^^ff^^c5^^ff^^bf, macro:->(\^^ff^^c5^^ff^^bf:m +acro:->あ).} +{TOT あ, ^^c5^^bf ^^c5^^bf 顛 , \^^ff^^c5^^ff^^bf, macro:->(\^^ff^^c5^^ff^^bf:m +acro:->あ).} +{MSG い, (\^^ff:macro:->い), \^^ff, macro:->(\^^ff:macro:->い).} +{TOT い, (\^^ff:macro:->い), \^^ff, macro:->(\^^ff:macro:->い).} +■contexts. +! Undefined control sequence. +\@->\A \undefined + +\a ->^^c5^^bf a^^c5^^bf ^^c5^^bf 顛 \@ + ^^c5^^bf 顛 +\+#1->\^^c5^^bf \顛 \^^ff^^c5^^ff^^bf #1 + \^^ff macro:->^^c5^^bf ^^c5^^bf 顛 ... +l.136 \+\a + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +\@->\A \undefined + +\a ->^^c5^^bf a^^c5^^bf ^^c5^^bf 顛 \@ + ^^c5^^bf 顛 +l.138 ...5^^ff^^bf ^^c5^^bf \^^c5^^bf ^^c5^^bf顛\a + \^^ff ^^ff\^^c5^^bf +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +l.140 \^^c5 + \^^ff\^^c4\^^fe +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +l.140 \^^c5\^^ff\^^c4 + \^^fe +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +l.140 \^^c5\^^ff\^^c4\^^fe + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +\^^c5^^bf\^^ff^^c5 +! Undefined control sequence. +\b ->\^^c5^^be + .\^^c5^^bf .\^^c5^^bd ..\転 .\顛 .\貼 . +l.154 \b + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +\b ->\^^c5^^be .\^^c5^^bf .\^^c5^^bd + ..\転 .\顛 .\貼 . +l.154 \b + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +\b ...5^^be .\^^c5^^bf .\^^c5^^bd ..\転 .\顛 .\貼 + . +l.154 \b + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +l.156 \^^c5^^be + .\^^c5^^bf.\^^c5^^bd..\転.\顛.\貼. +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +l.156 \^^c5^^be.\^^c5^^bf.\^^c5^^bd + ..\転.\顛.\貼. +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +l.156 \^^c5^^be.\^^c5^^bf.\^^c5^^bd..\転.\顛.\貼 + . +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +■csname2. +> \^^c5^^bf=macro: +->a. +l.162 SHOW \show\^^c5^^bf + .\show\顛.% + +> \顛=macro: +->b. +l.162 SHOW \show\^^c5^^bf.\show\顛 + .% + +> \^^c5^^bf=macro: +->a. + \^^c5^^bf + +l.163 \expandafter\show\csname ^^c5^^bf\endcsname + .% + +> \顛=macro: +->b. + \顛 + +l.164 \expandafter\show\csname 顛\endcsname + + +\^^e3^^81^^82\あ [50623] +Memory usage before: 1270&5512; after: 118&5077; still untouched: 4992459 + ) +Here is how much of TeX's memory you used: + 25 strings out of 497935 + 137 string characters out of 6219478 + 7541 words of memory out of 5000000 + 969 multiletter control sequences out of 15000+600000 + 3271 words of font info for 2 fonts, out of 8000000 for 9000 + 0 hyphenation exceptions out of 8191 + 6i,4n,2p,97b,22s stack positions out of 10000i,1000n,20000p,200000b,200000s + +Output written on p-pknj-e.dvi (1 page, 1140 bytes). diff --git a/source/texk/web2c/ptexdir/tests/pknj-s.log b/source/texk/web2c/ptexdir/tests/pknj-s.log new file mode 100644 index 000000000..7f753e894 --- /dev/null +++ b/source/texk/web2c/ptexdir/tests/pknj-s.log @@ -0,0 +1,223 @@ + restricted \write18 enabled. + %&-line parsing enabled. +**printkanji +(./printkanji.tex +\openout1 = `p-pknj-s.out'. + + +{MSG ^^c5^^bf ^^c5^^bf 顛 } +{TOT ^^c5^^bf ^^c5^^bf 顛 } +> \A=macro: +->^^c5^^bf ^^c5^^bf 顛 . +l.29 \show\A + + +■\meaning. {MSG macro:->macro:->^^c5^^bf ^^c5^^bf 顛 } +{TOT macro:->macro:->^^c5^^bf ^^c5^^bf 顛 } +> \B=macro: +->macro:->^^c5^^bf ^^c5^^bf 顛 . +l.40 \show\B + + +■\jobname. {MSG *あ*p-pknj-s*:p-pknj-s:*macro:->:p-pknj-s:*} +{TOT *あ*p-pknj-s*:p-pknj-s:*macro:->:p-pknj-s:*} + +■oneletter. {MSG \catcode`\^^c5= 197} +{TOT \catcode`\^^c5= 197} +{MSG \catcode`^^c5 = 197} +{TOT \catcode`^^c5 = 197} +{MSG \catcode`^^c5^^bf = 197} +{TOT \catcode`^^c5^^bf = 197} +{MSG \catcode`顛 = 37726} +{TOT \catcode`顛 = 37726} +■csname1. +> \顛=macro: +->hoge. +l.72 \show\顛 + + +> \^^c5^^bf=macro: +->piyo. +l.73 \show\^^c5^^bf + + +> \^^c5^^bf=macro: +->piyo. + \^^c5^^bf + +l.74 \expandafter\show\csname ^^c5^^bf\endcsname + + +{MSG \顛=>macro:->hoge} +{TOT \顛=>macro:->hoge} +{MSG \^^c5^^bf=>macro:->piyo} +{TOT \^^c5^^bf=>macro:->piyo} +{MSG \^^c5^^bf=>macro:->piyo} +{TOT \^^c5^^bf=>macro:->piyo} +{MSG \^^c5^^bf, \^^c5^^bf, \^^c5^^bf, \顛.} +{TOT \^^c5^^bf, \^^c5^^bf, \^^c5^^bf, \顛.} + +{MSG \あ=> hoge, \^^e3^^81^^82=> piyo. \^^e3^^81^^82=> piyo. } +{TOT \あ=> hoge, \^^e3^^81^^82=> piyo. \^^e3^^81^^82=> piyo. } +■0xFF. +{MSG あ, ^^c5^^bf ^^c5^^bf 顛 , \^^ff^^c5^^ff^^bf, macro:->(\^^ff^^c5^^ff^^bf:m +acro:->あ).} +{TOT あ, ^^c5^^bf ^^c5^^bf 顛 , \^^ff^^c5^^ff^^bf, macro:->(\^^ff^^c5^^ff^^bf:m +acro:->あ).} +{MSG い, (\^^ff:macro:->い), \^^ff, macro:->(\^^ff:macro:->い).} +{TOT い, (\^^ff:macro:->い), \^^ff, macro:->(\^^ff:macro:->い).} +■contexts. +! Undefined control sequence. +\@->\A \undefined + +\a ->^^c5^^bf a^^c5^^bf ^^c5^^bf 顛 \@ + ^^c5^^bf 顛 +\+#1->\^^c5^^bf \顛 \^^ff^^c5^^ff^^bf #1 + \^^ff macro:->^^c5^^bf ^^c5^^bf 顛 ... +l.136 \+\a + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +\@->\A \undefined + +\a ->^^c5^^bf a^^c5^^bf ^^c5^^bf 顛 \@ + ^^c5^^bf 顛 +l.138 ...5^^ff^^bf ^^c5^^bf \^^c5^^bf ^^c5^^bf顛\a + \^^ff ^^ff\^^c5^^bf +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +l.140 \^^c5 + \^^ff\^^c4\^^fe +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +l.140 \^^c5\^^ff\^^c4 + \^^fe +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +l.140 \^^c5\^^ff\^^c4\^^fe + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +\^^c5^^bf\^^ff^^c5 +! Undefined control sequence. +\b ->\^^c5^^be + .\^^c5^^bf .\^^c5^^bd ..\転 .\顛 .\貼 . +l.154 \b + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +\b ->\^^c5^^be .\^^c5^^bf .\^^c5^^bd + ..\転 .\顛 .\貼 . +l.154 \b + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +\b ...5^^be .\^^c5^^bf .\^^c5^^bd ..\転 .\顛 .\貼 + . +l.154 \b + +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +l.156 \^^c5^^be + .\^^c5^^bf.\^^c5^^bd..\転.\顛.\貼. +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +l.156 \^^c5^^be.\^^c5^^bf.\^^c5^^bd + ..\転.\顛.\貼. +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +! Undefined control sequence. +l.156 \^^c5^^be.\^^c5^^bf.\^^c5^^bd..\転.\顛.\貼 + . +The control sequence at the end of the top line +of your error message was never \def'ed. If you have +misspelled it (e.g., `\hobx'), type `I' and the correct +spelling (e.g., `I\hbox'). Otherwise just continue, +and I'll forget about whatever was undefined. + +■csname2. +> \^^c5^^bf=macro: +->a. +l.162 SHOW \show\^^c5^^bf + .\show\顛.% + +> \顛=macro: +->b. +l.162 SHOW \show\^^c5^^bf.\show\顛 + .% + +> \^^c5^^bf=macro: +->a. + \^^c5^^bf + +l.163 \expandafter\show\csname ^^c5^^bf\endcsname + .% + +> \顛=macro: +->b. + \顛 + +l.164 \expandafter\show\csname 顛\endcsname + + +\^^e3^^81^^82\あ [37726] +Memory usage before: 1274&5515; after: 118&5078; still untouched: 4992456 + ) +Here is how much of TeX's memory you used: + 24 strings out of 497935 + 135 string characters out of 6219475 + 7544 words of memory out of 5000000 + 968 multiletter control sequences out of 15000+600000 + 3271 words of font info for 2 fonts, out of 8000000 for 9000 + 0 hyphenation exceptions out of 8191 + 6i,4n,2p,97b,22s stack positions out of 10000i,1000n,20000p,200000b,200000s + +Output written on p-pknj-s.dvi (1 page, 1148 bytes). diff --git a/source/texk/web2c/ptexdir/tests/printkanji.tex b/source/texk/web2c/ptexdir/tests/printkanji.tex index a8f1d4cb5..d176d9a53 100644 --- a/source/texk/web2c/ptexdir/tests/printkanji.tex +++ b/source/texk/web2c/ptexdir/tests/printkanji.tex @@ -2,7 +2,16 @@ \tracingstats=1000 \noautoxspacing \newlinechar=`\^^J -\font\x=ec-lmtt10 \x +\font\x=ec-lmr10 \x +\ifx\kanjiskip\undefined\else + \ifnum\jis"2121="3000 + \jfont\jpy=umin10 at 10pt\jpy + \else + \jfont\jpy=min10 at 10pt\jpy + \fi +\fi + + \immediate\openout1=\jobname.out \def\MSG#1{% \message{\string{MSG #1\string}}% @@ -135,7 +144,6 @@ \catcode`\^^bf=11 \catcode`\^^bd=11 \catcode`\^^ff=11 -\font\x=ec-lmtt10 \x\scrollmode \def\^^c5^^bf{a} \def\顛{b} diff --git a/source/texk/web2c/ptexdir/tests/ucs-e.log b/source/texk/web2c/ptexdir/tests/ucs-e.log new file mode 100644 index 000000000..2e34c2ee9 --- /dev/null +++ b/source/texk/web2c/ptexdir/tests/ucs-e.log @@ -0,0 +1,25 @@ + restricted \write18 enabled. + %&-line parsing enabled. +**p-ucs +(./p-ucs.tex + +\ucs. +\cntA=\count26 +162: 41457 +163: 41458 +165: 41455 +167: 41464 +168: 41391 +172: 41676 +176: 41451 +177: 41438 +180: 41389 +182: 41721 +215: 41439 +247: 41440 +\toucs. +-1, -1, -1, -1, -1 +-1, 34821, 34722 +12354, 29081, -1 + ) +No pages of output. diff --git a/source/texk/web2c/ptexdir/tests/ucs-s.log b/source/texk/web2c/ptexdir/tests/ucs-s.log new file mode 100644 index 000000000..6ca6314c4 --- /dev/null +++ b/source/texk/web2c/ptexdir/tests/ucs-s.log @@ -0,0 +1,25 @@ + restricted \write18 enabled. + %&-line parsing enabled. +**p-ucs +(./p-ucs.tex + +\ucs. +\cntA=\count26 +162: 33169 +163: 33170 +165: 33167 +167: 33176 +168: 33102 +172: 33226 +176: 33163 +177: 33149 +180: 33100 +182: 33271 +215: 33150 +247: 33152 +\toucs. +-1, -1, -1, -1, -1 +12450, 29081, -1 +-1, -1, -1 + ) +No pages of output. diff --git a/source/texk/web2c/ptexdir/tests/ucs.tex b/source/texk/web2c/ptexdir/tests/ucs.tex index de8a32fc1..f4976ad70 100644 --- a/source/texk/web2c/ptexdir/tests/ucs.tex +++ b/source/texk/web2c/ptexdir/tests/ucs.tex @@ -9,7 +9,8 @@ \typeout{\string\ucs.} \newcount\cntA \loop\ifnum\cntA<256 - \ifnum0>\ucs\cntA\else\typeout{\the\cntA: \ucs\cntA (\Uchar\ucs\cntA)}\fi + \ifnum0>\ucs\cntA\else\typeout{\the\cntA: \ucs\cntA % + \ifx\Uchar\undefined\else(\Uchar\ucs\cntA)\fi}\fi \advance\cntA1 \repeat diff --git a/source/texk/web2c/tangle.ch b/source/texk/web2c/tangle.ch index 5bb61fe77..acf898630 100644 --- a/source/texk/web2c/tangle.ch +++ b/source/texk/web2c/tangle.ch @@ -73,7 +73,7 @@ procedure initialize; var @@/ begin @@/ @y -@ +@ procedure initialize; var @@/ begin @@ -302,6 +302,12 @@ the replacement text. chopped_id[s]:=buffer[i]+@'40 @z +@x [6.61] l.1086 +else @; +@y +else @; +@z + @x [6.63] l.1102 - Case smashing options/strict checking. if c<>"_" then begin if c>="a" then c:=c-@'40; {merge lowercase with uppercase} @@ -321,7 +327,7 @@ if l-double_chars=2 then {this string is for a single character} else begin equiv[p]:=string_ptr+@'100000; l:=l-double_chars-1; @y -@= +@= begin ilk[p]:=numeric; {strings are like numeric macros} if l-double_chars=2 then {this string is for a single character} equiv[p]:=buffer[id_first+1]+@'10000000000 @@ -681,7 +687,7 @@ Parse a Unix-style command line. @d argument_is (#) == (strcmp (long_options[option_index].name, #) = 0) -@ = +@ = procedure parse_arguments; const n_options = 9; {Pascal won't count array lengths for us.} var @!long_options: array[0..n_options] of getopt_struct; diff --git a/source/texk/web2c/tests/ec-lmr10.tfm b/source/texk/web2c/tests/ec-lmr10.tfm new file mode 100644 index 000000000..719e4f082 Binary files /dev/null and b/source/texk/web2c/tests/ec-lmr10.tfm differ diff --git a/source/texk/web2c/texprofdir/ChangeLog b/source/texk/web2c/texprofdir/ChangeLog new file mode 100644 index 000000000..a4079b330 --- /dev/null +++ b/source/texk/web2c/texprofdir/ChangeLog @@ -0,0 +1,16 @@ +2024-09-07 Karl Berry + + * am/texprof.am (texprofile_c): depend on texprofile-tangle, + not texprof-tangle. + (nodist_texprof_SOURCES): not needed, since these programs + have one source file; and texprof does not depend on texprofile. + +2024-09-02 Martin Ruckert + + Adding the texprofile manual page + +2024-09-02 Martin Ruckert + + Initial commit + +(This file public domain.) diff --git a/source/texk/web2c/texprofdir/README.TXT b/source/texk/web2c/texprofdir/README.TXT new file mode 100644 index 000000000..d099b850f --- /dev/null +++ b/source/texk/web2c/texprofdir/README.TXT @@ -0,0 +1,5 @@ +TeXprof is an extended version of TeX that collects run time data for the +TeXprofile program. + +TeXprof and TeXprofile together implement profiling for TeX input files. + diff --git a/source/texk/web2c/texprofdir/am/texprof.am b/source/texk/web2c/texprofdir/am/texprof.am new file mode 100644 index 000000000..6b5ae25f3 --- /dev/null +++ b/source/texk/web2c/texprofdir/am/texprof.am @@ -0,0 +1,76 @@ +## $Id$ +## texk/web2c/texprofdir/am/texprof.am: Makefile fragment for TeXprof +## +## Copyright 2024 Martin Ruckert +## You may freely use, modify and/or distribute this file. + +if TEXPROF +bin_PROGRAMS += texprof texprofile + +# convenience target to build all the programs here. +texprofall: texprof texprofile + +# See hitex.am for comments about handling man. +man1_MANS = texprofdir/man/texprof.man texprofdir/man/texprofile.man +endif TEXPROF + +texprof_CPPFLAGS = $(AM_CPPFLAGS) +texprof_CPPFLAGS += -I$(srcdir)/libmd5 +texprof_CPPFLAGS += -DINIT -DSTAT -DWEB2CVERSION="\"${WEB2CVERSION}\"" +# -DDEBUG drops into an interactive debugging session. +texprof_LDADD = $(KPATHSEA_LIBS) libmd5.a +texprof_DEPENDENCIES = $(KPATHSEA_DEPEND) libmd5.a +# +texprofile_CPPFLAGS = $(AM_CPPFLAGS) +texprofile_LDADD = +texprofile_DEPENDENCIES = +# +# TeXprof CWEB sources +texprof_web = texprofdir/texprof.w +texprofile_web = texprofdir/texprofile.w + +# Creating several files: need stamp file and two rules with identical recipes +texprof_ctangle_sh = CWEBINPUTS=$(srcdir)/texprofdir AM_V_P=$(AM_V_P) $(SHELL) ./tangle-sh $@ $(CTANGLE) + +# For each cweb (.w) source file, list the files generated. +texprof_c = texprof.c +texprofile_c = texprofile.c + +$(texprof_c): texprof-tangle +$(texprofile_c): texprofile-tangle + +# +texprof-tangle: ctangle$(EXEEXT) texprofdir/texprof.w tangle-sh + $(texprof_ctangle_sh) texprof + +texprofile-tangle: ctangle$(EXEEXT) texprofdir/texprofile.w tangle-sh + $(texprof_ctangle_sh) texprofile + +EXTRA_DIST += texprofdir/ChangeLog $(texprof_web) + +DISTCLEANFILES += $(nodist_texprof_SOURCES) +DISTCLEANFILES += texprofile-tangle texprof-tangle + +## TeXprof tests +# +#texprof_tests = texprofdir/tests/hello.test \ +# texprofdir/tests/rule.test +# +#texprofdir/tests/hello.log: texprof$(EXEEXT) histretch$(EXEEXT) +#texprofdir/tests/rule.log: texprof$(EXEEXT) histretch$(EXEEXT) hishrink$(EXEEXT) +# +#EXTRA_DIST += $(texprof_tests) +# +#if TEXPROF +#TESTS += $(texprof_tests) +#endif TEXPROF +# +## hello.test +#EXTRA_DIST += texprofdir/tests/hello.tex +#DISTCLEANFILES += hello.log + +## rule.test +#EXTRA_DIST += texprofdir/tests/rule.tex +#DISTCLEANFILES += rule.log + +# (end of texprof.am) diff --git a/source/texk/web2c/texprofdir/doc/texprof.hnt b/source/texk/web2c/texprofdir/doc/texprof.hnt new file mode 100644 index 000000000..fb3d7c162 Binary files /dev/null and b/source/texk/web2c/texprofdir/doc/texprof.hnt differ diff --git a/source/texk/web2c/texprofdir/doc/texprof.pdf b/source/texk/web2c/texprofdir/doc/texprof.pdf new file mode 100644 index 000000000..d07addfa3 Binary files /dev/null and b/source/texk/web2c/texprofdir/doc/texprof.pdf differ diff --git a/source/texk/web2c/texprofdir/doc/texprofile.hnt b/source/texk/web2c/texprofdir/doc/texprofile.hnt new file mode 100644 index 000000000..507675ef3 Binary files /dev/null and b/source/texk/web2c/texprofdir/doc/texprofile.hnt differ diff --git a/source/texk/web2c/texprofdir/doc/texprofile.pdf b/source/texk/web2c/texprofdir/doc/texprofile.pdf new file mode 100644 index 000000000..eca97af55 Binary files /dev/null and b/source/texk/web2c/texprofdir/doc/texprofile.pdf differ diff --git a/source/texk/web2c/texprofdir/doc/texprofileman.hnt b/source/texk/web2c/texprofdir/doc/texprofileman.hnt new file mode 100644 index 000000000..8cd8af1aa Binary files /dev/null and b/source/texk/web2c/texprofdir/doc/texprofileman.hnt differ diff --git a/source/texk/web2c/texprofdir/doc/texprofileman.pdf b/source/texk/web2c/texprofdir/doc/texprofileman.pdf new file mode 100644 index 000000000..57e23386a Binary files /dev/null and b/source/texk/web2c/texprofdir/doc/texprofileman.pdf differ diff --git a/source/texk/web2c/texprofdir/man/texprof.man b/source/texk/web2c/texprofdir/man/texprof.man new file mode 100644 index 000000000..b83047e95 --- /dev/null +++ b/source/texk/web2c/texprofdir/man/texprof.man @@ -0,0 +1,345 @@ +.TH TEXPROF 1 "2 September 2024" "Version 1.0" +.\"===================================================================== +.if n .ds MF Metafont +.if t .ds MF Metafont +.if t .ds TX \fRT\\h'-0.1667m'\\v'0.20v'E\\v'-0.20v'\\h'-0.125m'X\fP +.if n .ds TX TeX +.ie t .ds OX \fIT\v'+0.25m'E\v'-0.25m'X\fP +.el .ds OX TeX +.\" BX definition must follow TX so BX can use TX +.if t .ds BX \fRB\s-2IB\s0\fP\*(TX +.if n .ds BX BibTeX +.\" LX definition must follow TX so LX can use TX +.if t .ds LX \fRL\\h'-0.36m'\\v'-0.15v'\s-2A\s0\\h'-0.15m'\\v'0.15v'\fP\*(TX +.if n .ds LX LaTeX +.if t .ds AX \fRA\\h'-0.1667m'\\v'0.20v'M\\v'-0.20v'\\h'-0.125m'S\fP\*(TX +.if n .ds AX AmSTeX +.if t .ds AY \fRA\\h'-0.1667m'\\v'0.20v'M\\v'-0.20v'\\h'-0.125m'S\fP\*(LX +.if n .ds AY AmSLaTeX +.if n .ds WB Web +.if t .ds WB W\s-2EB\s0 +.\"===================================================================== +.SH NAME +texprof \- A profiler for TeX source files +.SH SYNOPSIS +.B texprof +.RI [ options ] +.RI [ \fB&\fPformat ] +.RI [ file | \fB\e\fPcommands ] +.\"===================================================================== +.SH DESCRIPTION +Run the \*(TX profiler on +.IR file , +usually creating +.IR file.dvi +and +.IR file.tprof . +If the +.IR file +argument has no extension, ".tex" will be appended to it. +Instead of a file name, a list of \*(TX commands can be given, the first +of which must start with a backslash. +With a +.BI & format +argument, the \*(TX profiler uses a different set of precompiled commands, +contained in +.IR format\fB.fmt\fP ; +it is usually better to use the +.B -fmt +.I format +option instead. +.PP +The \*(TX profiler is a version of \*(TX that measures the time +\*(TX needs to execute individual input lines or macros. +It writes the collected data to a file with extension +.IR .tprof . +A separate program, +.B texprofile +(see +.BR texprofile (1)), +is used to display the content of a +.IR .tprof +file in a readable form. + +.PP +The typical use of the \*(TX profiler is with pre generated formats. +The +.B texprof +command uses the equivalent of the plain \*(TX format, and the +.B latexprof +command uses the equivalent of the \*(LX format. To investigate +the timing of macros targeted to +.B pdftex +or +.B pdflatex, +you can use +.B pdftexprof +or +.B pdflatexprof. + +.PP +The \*(TX profiler's handling of its command-line arguments is similar +to that of the other \*(TX programs in the +.I web2c +implementation. + +.\"===================================================================== +.SH OPTIONS +This version of the \*(TX profiler understands the following command line +options. +.TP +.BI -cnf-line \ string +Parse +.I string +as a +.I texmf.cnf +configuration line. See the Kpathsea manual. +.TP +.B -etex +Enable the e-\*(TX extensions. This option is only effective in +combination with +.BR -ini . +See +.BR etex (1). +.TP +.B -file-line-error +Print error messages in the form +.I file:line:error +which is similar to the way many compilers format them. +.TP +.B -no-file-line-error +Disable printing error messages in the +.I file:line:error +style. +.TP +.BI -fmt \ format +Use +.I format +as the name of the format to be used, instead of the name by which +the \*(TX profiler was called or a +.I %& +line. +.TP +.B -help +Print help message and exit. +.TP +.B -ini +Start in +.I INI +mode, which is used to dump formats. The +.I INI +mode can be used for typesetting, but no format is preloaded, and +basic initializations like setting catcodes may be required. +.TP +.BI -interaction \ mode +Sets the interaction mode. The mode can be either +.IR batchmode , +.IR nonstopmode , +.IR scrollmode , +and +.IR errorstopmode . +The meaning of these modes is the same as that of the corresponding +\ecommands. +.TP +.BI -jobname \ name +Use +.I name +for the job name, instead of deriving it from the name of the input file. +.TP +.BI -kpathsea-debug \ bitmask +Sets path searching debugging flags according to the bitmask. See the +.I Kpathsea +manual for details. +.TP +.B -ltx +Enable the \*(LX extensions. This option is only effective in +combination with +.BR -ini . +See +.BR latex (1). +.TP +.BI -mktex \ fmt +Enable +.RI mktex fmt , +where +.I fmt +must be either +.IR tex , +.IR tfm , +.IR fmt , +or +.IR pk . +.TP +.BI -no-mktex \ fmt +Disable +.RI mktex fmt , +where +.I fmt +must be either +.IR tex , +.IR tfm , +.IR fmt , +or +.IR pk . +.TP +.BI -output-directory \ directory +Write output files in +.I directory +instead of the current directory. Look up input files in +.I directory +first, then along the normal search path. +.TP +.B -parse-first-line +If the first line of the main input file begins with +.I %& +parse it to look for a dump name. +.TP +.B -no-parse-first-line +Disable parsing of the first line of the main input file. +.TP +.B -pdf +Enable the simulation of common +.B pdftex +primitives. This option requires the +.BR -ini +option and implies the +.BR -ltx +option. +See +.BR pdftex (1). +.TP +.B -prof +Enable profiling as soon as \*(TX enters the main loop. If tis option +it not used, profiling needs to switched on using the \eprofileon +primitive. Profiling can be switched of with the \eprofileoff +primitive. +.TP +.BI -progname \ name +Pretend to be program +.IR name . +This affects both the format used and the search paths. +.TP +.B -version +Print version information and exit. +.\"===================================================================== +.SH ENVIRONMENT +See the Kpathsea library documentation (e.g., the `Path specifications' +node) for precise details of how the environment variables are used. +The +.B kpsewhich +utility can be used to query the values of the variables. +.PP +.TP +.B TEXMFOUTPUT +Normally, \*(TX puts its output files in the current directory. If +any output file cannot be opened there, it tries to open it in the +directory specified in the environment variable TEXMFOUTPUT. +There is no default value for that variable. For example, if you say +.I texprof paper +and the current directory is not writable and TEXMFOUTPUT has +the value +.IR /tmp , +\*(TX attempts to create +.I /tmp/paper.log , +.I /tmp/paper.dvi , +and +.I /tmp/paper.tprof . +TEXMFOUTPUT is also checked for input +files, as \*(TX often generates files that need to be subsequently +read; for input, no suffixes (such as ``.tex'') are added by default, +the input name is simply checked as given. +.TP +.B TEXINPUTS +Search path for +.I \einput +and +.I \eopenin +files. +This normally starts with ``.'', so +that user files are found before system files. An empty path +component will be replaced with the paths defined in the +.I texmf.cnf +file. For example, set TEXINPUTS to ".:/home/user/tex:" to prepend the +current directory and ``/home/user/tex'' to the standard search path. +.TP +.B TEXFORMATS +Search path for format files. +.TP +.B TFMFONTS +Search path for font metric +.RI ( .tfm ) +files. +.TP +.B SOURCE_DATE_EPOCH +If set, its value, taken to be in epoch-seconds, will be used for the +creation date and as the reference moment for the time related +primitives of \*(LX. This is useful for making reproducible builds. +.TP +.B FORCE_SOURCE_DATE +If set to the value "1", the time-related \*(TX primitives +.RI ( \eyear , +.IR \emonth , +.IR \eday , +.IR \etime ) +are also initialized from the value of SOURCE_DATE_EPOCH. This is not +recommended if there is any viable alternative. +.PP +Many, many more environment variables may be consulted related to path +searching. See the Kpathsea manual. +.\"===================================================================== +.SH FILES +The location of the files mentioned below varies from system to +system. Use the +.B kpsewhich +utility to find their locations. +.TP +.I *.tfm +Metric files for \*(TX's fonts. +.TP +.I *.fmt +Predigested \*(TX format files. +.TP +.I *.pk *.pfb +Font files used by \*(TX. +.\"===================================================================== +.SH NOTES +This manual page is not meant to be exhaustive. The complete +documentation for the \*(TX profiler can be found in +.IR texprof.pdf . +Further information can be found in the manual of the +.IR "Kpathsea library" . +.\"===================================================================== +.SH BUGS +This version of the \*(TX profiler does not implement all of the +primitives that pdftex provides, and further, it will not produce +the same side effects. +.\"===================================================================== +.SH AVAILABILITY +The \*(TX profiler should compile on a large variety of machine architectures +and operating systems. The function to obtain timing information id POSIX +specific. +.PP +The sources of the \*(TX profiler are hosted at +.BR https://github.com/ruckertm/HINT +.\"===================================================================== +.SH "SEE ALSO" +.BR texprofiler (1), +.BR tex (1), +.BR latex (1), +.BR pdftex (1), +.BR pdflatex (1), and +.BR kpsewhich (1). +.\"===================================================================== +.SH AUTHORS +The primary author of the \*(TX profiler is Martin Ruckert, +with e\*(TX extensions by Peter Breitenlohner, +\*(LX extensions by Thierry Laronde, +and +the kpathsearch library by Karl Berry. +.PP +\*(TX was designed by Donald E. Knuth, +who implemented it using his \*(WB system for Pascal programs. +.PP +Many, many more contributed to the typesetting system now known as \*(TX; +far too many to name all of them here. +.\" vim: syntax=nroff diff --git a/source/texk/web2c/texprofdir/man/texprofile.man b/source/texk/web2c/texprofdir/man/texprofile.man new file mode 100644 index 000000000..6fe0ce616 --- /dev/null +++ b/source/texk/web2c/texprofdir/man/texprofile.man @@ -0,0 +1,596 @@ +'\" t +.\" Manual page created with latex2man on Mon Sep 9 16:27:26 2024 +.\" NOTE: This file is generated, DO NOT EDIT. +.de Vb +.ft CW +.nf +.. +.de Ve +.ft R + +.fi +.. +.TH "TEXPROFILE" "1" "6\-9\-2024" "Displaying TeX profiles " "Displaying TeX profiles " +.SH NAME + +.PP +texprofile +\- Displaying the profile data collected by texprof\&. +.PP +.SH SYNOPSIS + +.PP +texprofile +[Options] \fIinputfile\fP +.PP +.SH DESCRIPTION + +texprofile +reads the binary \fIinputfile\fP +as produced by +texprof\&. +The extension \&.tprof +of the input file can be +omitted. It analyses the data and presents the results in a variety of +tables, either optimized for human readability or as CSV (comma +separated values) files for further processing. +.PP +The output is written to the standard output stream where it can be redirected +to a file or viewed immediately. +.PP +.SH OPTIONS + +There are four types of options: general options, table options, +selection options, and formatting options. +.PP +The general options: +.TP +\fB\-?\fP \fB\-h\fP \fB\-\-help\fP + Display a short help text and exit the program. +.TP +\fB\-\-version\fP + Display the version information and exit. +.PP +The table options determine the tables that will be displayed. +These options all use upper case letters. +If no table option is given, only some global information is shown. +.PP +.TP +\fB\-T\fP + Show the table of the top 10 input lines. +.TP +\fB\-G\fP + Show the table of the macro call graph. +.TP +\fB\-C\fP + Show the table of times per TeX command. +.TP +\fB\-L\fP + Show the table of times per input line. +.TP +\fB\-R\fP + Show the table of raw time stamps. +.TP +\fB\-S\fP + Show the table of macro stack changes. +.TP +\fB\-F\fP + Show the table of all input files. +.TP +\fB\-M\fP + Show the table of all macros called. +.TP +\fB\-A\fP + Show important tables (equal to \-TGFC) tables. +.TP +\fB\-N\fP + Do not show the table of global information. +.PP +The selection options allow to reduce the amount of data that is shown +in the table by omitting table entries that contribute little to the +overall runtime. +.PP +.TP +\fB\-p\fP\fIn\fP + Do not show information for table entries +with cumulative time below \fIn\fP +percent. The default is 1.0 percent. +.TP +\fB\-t\fP\fIn\fP + Limit the number of input lines shown in the +table of the ``Top Ten\&'' to \fIn\fP\&. +This option is only useful +with the \fB\-T\fP +option. +.PP +The formatting option determine the formatting of the information in the tables +as well as the selection of information that is shown in the tables. +.PP +.TP +\fB\-i\fP + Add the macros file and line numbers after the macro name. +This option is useful to distinguish two macros that share +the same name. +.TP +\fB\-m\fP + Optimize output for machine readability. When optimized for human readability, +times are rounded and given in a short form adding a unit identifier: +s for seconds, ms for milliseconds, us for micro seconds, and ns for +nanoseconds. This format is inconvenient if you want to import the data +for example into a spread\-sheet for further processing. +With the \fB\-m\fP +option times are simply given in nano seconds without units. +Similar the combined time for the total time used for a macro and the +time used as a sub\-macro from the call graph is given in a single column +with a slash separating both numbers is nice for human readers. +With the \fB\-m\fP +option both numbers will simply be given in separate columns. +.PP +.TP +\fB\-n\fP + Show the time stamp numbers. This option is useful together with +the \fB\-R\fP +option, if you import the table into a database or spread\-sheet. +If you sort the data by various properties into different +categories, the time stamp number can be used to keeping the entries +within a category sorted by time. +.PP +.TP +\fB\-s\fP + Show the changes of the macro stack. +This option is useful with the \fB\-R\fP +option if you want to see the changes +in the macro stack (see \fB\-S\fP) +together with the timing information in +a single table. +.PP +.SH DATA FORMATS + +.SS FILE NUMBERS +While texprof +is running, every TeX input file is given a +unique file number. The file name alone is often not unique because +two files in different directories might have the same file +name. Displaying the full file name with the complete path is however often +not very +convenient. So if you observe the same file name together with +different file numbers, you can use the option \fB\-F\fP +to get a table of all +file numbers and their full file names. +.PP +But even within the same +directory, TeX can read different files with the same name during one +run: TeX can open a file for writing, write content to the file, close +it, open it for reading, read it and close it again. Then TeX might +repeat this process a second time, or multiple times, reusing the same +file name over and over again. texprof +will assign a new file +number to this file each time it is opened for reading. So you can +tell from the sequence of file numbers which one was the first, the +second, or the third. +.PP +Last not least, there are some special file +numbers: +.TP +0 \- unknown +If the file is unknown, which should rarely happen, +the file number 0 is used. +.TP +1\- system +texprof +will map +time intervals that are used to execute certain system routines +to the ``system\&'' pseudo file +using the line numbers to identify the specific routine +like producing the output DVI file (shipout), breaking +a paragraph into lines (linebrk), or breaking the +document into pages (buildpg). These times do not depend on the +use of macros but simply on the size of the document. +.TP +2 \- terminal +TeX commands entered on the command line or interactively are mapped +to file number 2. +.PP +.SS TIME +If the option \fB\-m\fP +is given times are given as nanoseconds. +Otherwise, times are rounded to at most 4 digits precission and +displayed with a unit: seconds (s), milliseconds (ms), microseconds +(um), or nanoseconds (ns). +.PP +.SS MACRO NAMES +Macro names are shown with the leading backslash. Since macro names +are often not unique, the command line option \fB\-i\fP +can be used to +show after the macro name in square brackets the file number and the +line number where the macro is defined. Unless two macros with the +same name are defined in the same file and line this is sufficient to +uniquely identify a macro. A macro defined with ``let\&'' results in a +complet copy of the original macro. Therefore it will not reference +the file and line of the ``let\&'' command but the same file and line as +the original macro. +.PP +.SH EXAMPLES + +Let\&'s assume that you issue the command texprof +\fB\-prof\fP +\fIhello.tex\fP\&. +This will run texprof +on the input file +\fIhello.tex\fP +with option \fB\-prof\fP\&. +The program texprof +will load the plain TeX format and then process hello.tex +to +produce hello.log +and hello.dvi\&. +It will execute +exactly the same steps that TeX would execute if you had issued the +command tex +\fIhello.tex\fP\&. +.PP +In addition to hello.log +and hello.dvi, +texprof +will also produce the file hello.tprof +containing time +measurements made while texprof +was running. The option +\fB\-prof\fP +will switch on the gathering of timing data as soon as +texprof +enters its main control procedure; The file +hello.tprof +will contain a time measurement, called a time +stamp, for every command that TeX executed while processing the input. +A binary format is used to store all that data in a simple and compact +form. Still the file hello.tprof +might become very big. +.PP +The program texprofile +is used to extract and analyse the data +contained in hello.tprof +and produce useful output. Here are +some examples: +.PP +.TP +texprofile \fIhello\fP + Without further options texprofile +will write some general +information to the standard output, like the total time measured, +the number of samples, the average time per sample, etc. +The general information is always given unless explicitely disabled +with the \fB\-N\fP +option or with the \fB\-m\fP +option. +.PP +.TP +texprofile \fB\-T\fP \fIhello\fP + With the option \fB\-T\fP, +texprofile +will map each time stamp +to a specific line of input, add up the time intervalls for each input +line separately, and output a table showing the ten lines that have +the highest cummulative time. +The table has the following seven columns: +.RS +.TP +1. file +The first column contains the input file number as explained above. +The input file name if shown in column 7. +.TP +2. line +The line number. +.TP +3. percent +The time spent in this line and file as a percentage of the total +time measured as given as part of the general information. +.TP +4. absolute +The absolute time spent in this line and file. +.TP +5. count +The number of times the execution path entered this line. +Note, that a +macro call usually redirects the execution path to another line +from where the execution will return after the macro call has completed. +Reentering the line after such an excursion to an other line will +cause this counter to be incremented. In summary, this counter might +reflect the number of partial executions of a line not the number +of full executions of the entire line. +.TP +6. average +The average time spent in the line is simply computed by dividing the +value in column 4 by the value in column 5. +.TP +7. file +The input file name. The corresponding file number is shown in column 1. +.RE +.RS +.PP +.RE +.TP +texprofile \fB\-G\fP \fIhello\fP + With the option \fB\-G\fP, +texprofile +will map each time stamp +either to file input or to a macro body. +The table shown is divided into several sections, the first section +is devoted to file input, each of the following sections is devoted +to a specific macro. +.br +Each section starts with a header. The header of the +first section is ``File\&'' the header of a later section is the macro name. +.br +The first line after the header gives the total time spent in the section +in two different formats: +.RS +.TP +1. time +Column 1 gives it as an absolut time. +.TP +3. percentage +Column 3 gives it as a percentage of the total time measured. +.RE +.RS +.PP +For the first section with the header ``File\&'', the absolute time +will be equal to the total time measured because texprof +did spent all the time processing the file \fIhello\fP\&. +And consequently the value in column 3 will be 100%\&. +.br +To accomplish a task, a macro usually calls other +macros that we call child macros in the following. +The following lines in the table will give a breakdown +of the time shown in the first line. +The breakdown starts with a line showing the time spent in the section +excluding the time spent in child macros. It shows in column 4 the number +of times the macro was called. +.RS +.RE +.TP +1. time +Column 1 gives the absolut time spent in the section excluding the time +spent in child macros +.TP +3. percentage +Column 3 gives the time from column 1 as a percentage of the total time +spent in this section as given in the previous line. +.TP +4. count/total +Column 4 gives the number of times the section was called. +.RE +.RS +.PP +The lines that follow in the table show the time spent in one of +the child macros. Column 2, 4, and 5 need some explanation. +.RS +.RE +.TP +2. loop +The only case where column 2 is not empty is the case of a +recursive macro. A recursive macro is a macro that along the +chain of macro calls eventually calls itself creating a +recursive loop. At this point, a macro becomesits own descendant +and at the same time its own ancestor. +.br +Therefore texprofile +maintains for each child macro two +accumulators for the elapsed time: For the time shown in +column 2 labeled ``loop\&'', texprofile +adds up the time +differences observed at the return of a child macro. For the +time shown in the column labeled ``time\&'' and ``percent\&'', it +subtracts from the time differences observed at the return of a +child macro all those time differences that were already added +to one of the other lines in the time breakdown: the macro itself +or one of the other child macros. +So the times shown in column 1 of line 2 and the following lines +will add up to the time shown in column 1 of the line 1; +and the percentages shown in column 3 of line 2 and the following lines +will add up to 100%\&. +The time shown in column 3 will show show the total time needed +to accomplish the sub task assigned to the respective child macro. +.TP +4. count/total +Column 4 shows two counts n/m for the macro named in column 5. +m is the total number of calls to the macro and n is the number of +calls as a child macro in the current section. The number n will +always be less or equal to m\&. +.RS +.PP +.RE +.TP +5. child +Column 5 shows the name of the child macro as explained above. +.RE +.RS +.PP +.RE +.TP +texprofile \fB\-G\fP \fB\-m\fP \fIhello\fP + This table will contain the same data as the previous example +but this time the \fB\-m\fP +option will optimize the output for +machine readability. +.RS +.TP +.B * +There are no column headers. +.TP +.B * +The times in column 1 ``time\&'' and column 2 ``loop\&'' +are given in nanoseconds without a unit identifier. +.TP +.B * +The numbers n/m in column 4 are now shown in two separate +columns 4 and 5; the macro name moves from column 5 to column 6. +.RE +.RS +.PP +.RE +.TP +texprofile \fB\-F\fP \fIhello\fP + With the option \fB\-F\fP, +texprofile +outputs the table +of all of TeX\&'s input files using 5 columns: +.RS +.TP +1. file +The file number as explained above. +.TP +2. lines +The difference between the highest and the lowest +line number found in the profile data for this file. This is +usually only a subset of all the lines of the file. +.TP +3. percent +The percentage of the total time measured that is attibuted to the file. +.TP +4. time +The absolute time that is attibuted to the file. +.TP +5. name +The full file name of the file. +.RE +.RS +.PP +.RE +.TP +texprofile \fB\-C\fP \fIhello\fP + With the option \fB\-C\fP, +texprofile +outputs the table +of all TeX commands executed while profiling +using 6 columns: +.RS +.TP +1. cmd +The command code used internaly by TeX. +Usually the same number is used by TeX for several +closely related tasks. +There is a special command code 101 which is used to +for the time that is spend on system routines that are +mapped to the system file as explained above. +.TP +2. time +The total time used for the command. +.TP +3. percent +The percentage of the total time measured used for the command. +.TP +4. count +The number of times this command was executed. +.TP +5. average +The average time needed to execute the command. +This is simpy the value in column 2 divided by the value in column 4. +.TP +6. name +A verbal description of the command or commands that share this +command code. +.RE +.RS +.PP +.RE +.TP +texprofile \fB\-R\fP \fB\-m\fP \fB\-n\fP \fIhello\fP + With the options \fB\-R\fP +\fB\-m\fP, +texprofile +outputs the table +of raw time measurements as observed by texprof +optimized for machine +readability. The option \fB\-n\fP +adds a column for the number +of each time measurements. +Because of the \fB\-m\fP +option, the table has no column headers. +The table has 7 columns: +.RS +.TP +1. number +The number of the time measurment. +These numbers are strictly increasing but not necessarily consecutive. +They can be used to keep the measurements sorted in the order in which +they were made. +.TP +2. file +The file number as explained above. +.TP +3. line +The line number as explained above. +.TP +4. time +The time interval in nano seconds. +.TP +5. command +The command name as given in column 6 of the previous example. +.TP +6. level +The nesting level of the macro call stack. +.TP +7. macro +The macro name. +.RE +.RS +.PP +This table contains all the timing information gathered during the run +of texprof\&. +Some information about macro calls is contained in +column 6. More information about macro calls could be added +by using the \fB\-s\fP +option. The information about macro returns +can be obtained from column 6. +The table can be imported to a spread\-sheet or a database for further +analysis. +.RE +.PP +.SH BUGS + +If the last command in a macro body is a macro call, we call this a tail call. +If such a tail call reads ahead to scan the following input +for possible arguments, the look\-ahead mechaism of TeX might push further +macros or new input files on TeX\&'s input stack. +These entries will remain on top of TeXprof\&'s macro nesting stack, +even if TeX backs up all these tokens on its input stack. +This can cause an attribution of runtime to those entries as sub entries +of the tail call. If this explanation sounds complicated to you, it is +because the situation is indeed complicated. +.PP +.SH SEE ALSO + +\fItexprof\fP(1) +.PP +.SH VERSION + +Version: 1.0 of 6-9-2024 +.TP +Copyright +(C)2024, Martin Ruckert, +.br +Hochschule München, Lothstrasse 64, D\-80335 München +.PP +.TP +Distribution +texprofile +is distributed with TeX Live. +More recent versions might be found on GitHub +\fBhttps://github.com/ruckertm/HINT\fP\&. +.PP +.TP +License +This program can be redistributed and/or modified under the +terms of the MIT/X11 license. +.PP +.SH AUTHOR + +Martin Ruckert +.br +Munich University of Applied Sciences +.br +Email: \fBmartin.ruckert@hm.edu\fP +.br +.PP +.\" NOTE: This file is generated, DO NOT EDIT. diff --git a/source/texk/web2c/texprofdir/tex/latexprof.ini b/source/texk/web2c/texprofdir/tex/latexprof.ini new file mode 100644 index 000000000..889e6bec4 --- /dev/null +++ b/source/texk/web2c/texprofdir/tex/latexprof.ini @@ -0,0 +1 @@ +\input latex.ltx diff --git a/source/texk/web2c/texprofdir/tex/pdflatexprof.ini b/source/texk/web2c/texprofdir/tex/pdflatexprof.ini new file mode 100644 index 000000000..0460d192e --- /dev/null +++ b/source/texk/web2c/texprofdir/tex/pdflatexprof.ini @@ -0,0 +1,2 @@ +\pdfoutput=1 +\input latex.ltx diff --git a/source/texk/web2c/texprofdir/tex/pdftexprof.ini b/source/texk/web2c/texprofdir/tex/pdftexprof.ini new file mode 100644 index 000000000..8ee45c922 --- /dev/null +++ b/source/texk/web2c/texprofdir/tex/pdftexprof.ini @@ -0,0 +1,3 @@ +\pdfoutput=1 +\input plain.tex +\dump diff --git a/source/texk/web2c/texprofdir/tex/texprof.ini b/source/texk/web2c/texprofdir/tex/texprof.ini new file mode 100644 index 000000000..74e0658f5 --- /dev/null +++ b/source/texk/web2c/texprofdir/tex/texprof.ini @@ -0,0 +1,2 @@ +\input plain.tex +\dump diff --git a/source/texk/web2c/texprofdir/texprof.w b/source/texk/web2c/texprofdir/texprof.w new file mode 100644 index 000000000..722106017 --- /dev/null +++ b/source/texk/web2c/texprofdir/texprof.w @@ -0,0 +1,33304 @@ +% TeXprof is copyright (C) 2024 by Martin Ruckert +% Hochschule Muenchen, Lothstrasse 64, 80336 Muenchen +% and put under the MIT/X11 license. +% +% Prote is copyright (C) 2021 by Thierry Laronde and put under +% the MIT/X11 license. +% +% As TeX and e-TeX are reserved names for the unchanged (except for the +% necessary implementation of system dependencies) instances of, resp., +% Donald E. Knuth's program and the NTS team's e-TeX implementation, the +% name Prote is reserved for this kerTeX implementation. +% +% Hence, this is neither TeX (even if it is compatible at start) nor +% e-TeX (even if is compatible when entering the first set of +% extensions). + +% Version 0 was released in September 1982 after it passed a variety of tests. +% Version 1 was released in November 1983 after thorough testing. +% Version 1.1 fixed ``disappearing font identifiers'' et alia (July 1984). +% Version 1.2 allowed `0' in response to an error, et alia (October 1984). +% Version 1.3 made memory allocation more flexible and local (November 1984). +% Version 1.4 fixed accents right after line breaks, et alia (April 1985). +% Version 1.5 fixed \the\toks after other expansion in \edefs (August 1985). +% Version 2.0 (almost identical to 1.5) corresponds to "Volume B" (April 1986). +% Version 2.1 corrected anomalies in discretionary breaks (January 1987). +% Version 2.2 corrected "(Please type...)" with null \endlinechar (April 1987). +% Version 2.3 avoided incomplete page in premature termination (August 1987). +% Version 2.4 fixed \noaligned rules in indented displays (August 1987). +% Version 2.5 saved cur_order when expanding tokens (September 1987). +% Version 2.6 added 10sp slop when shipping leaders (November 1987). +% Version 2.7 improved rounding of negative-width characters (November 1987). +% Version 2.8 fixed weird bug if no \patterns are used (December 1987). +% Version 2.9 made \csname\endcsname's "relax" local (December 1987). +% Version 2.91 fixed \outer\def\a0{}\a\a bug (April 1988). +% Version 2.92 fixed \patterns, also file names with complex macros (May 1988). +% Version 2.93 fixed negative halving in allocator when mem_min<0 (June 1988). +% Version 2.94 kept open_log_file from calling fatal_error (November 1988). +% Version 2.95 solved that problem a better way (December 1988). +% Version 2.96 corrected bug in "Infinite shrinkage" recovery (January 1989). +% Version 2.97 corrected blunder in creating 2.95 (February 1989). +% Version 2.98 omitted save_for_after at outer level (March 1989). +% Version 2.99 caught $$\begingroup\halign..$$ (June 1989). +% Version 2.991 caught .5\ifdim.6... (June 1989). +% Version 2.992 introduced major changes for 8-bit extensions (September 1989). +% Version 2.993 fixed a save_stack synchronization bug et alia (December 1989). +% Version 3.0 fixed unusual displays; was more \output robust (March 1990). +% Version 3.1 fixed nullfont, disabled \write{\the\prevgraf} (September 1990). +% Version 3.14 fixed unprintable font names and corrected typos (March 1991). +% Version 3.141 more of same; reconstituted ligatures better (March 1992). +% Version 3.1415 preserved nonexplicit kerns, tidied up (February 1993). +% Version 3.14159 allowed fontmemsize to change; bulletproofing (March 1995). +% Version 3.141592 fixed \xleaders, glueset, weird alignments (December 2002). +% Version 3.1415926 was a general cleanup with minor fixes (February 2008). +% Version 3.14159265 was similar (January 2014). +% Version 3.141592653 was similar but more extensive (January 2021). + +% A reward of $327.68 will be paid to the first finder of any remaining bug. + +% This is the 1.1 version of Prote, developed during August 2021, +% and corrected during september/october 2021 and amended in august 2023 +% for file primitives behavior matching input behavior. +% +% 1.0: adds primitives needed by LaTeX as listed in ltnews31. +% - 2022-07-21: tiddying formal fix: a spurious line was a left over +% of a removed paragraph (pointed by Martin Ruckert). Suppressed. +% +% 1.1: 2023-08-01: the new file primitives are used in LaTeX expecting +% the input behavior that ".tex" be appended if no extension. So +% modified to provide this. +% +% History towards 1.0 release: +% 0.99.4: +% - typos and style corrections provided by Martin Ruckert for +% clean translation in Pascal (forward declarations and underscores +% omitted); +% - adjustements against e-TeX 2.6 instead of 2.1 (T. Laronde). +% 0.99.7: +% - \expanded was using an e-TeX procedure not doing def handling +% => using scan_toks() now. Reported by Martin Ruckert and +% test code narrowed down by Phelype Oleinik. +% 0.99.8: +% - \expanded again: scan_toks() sets def_ref. But back_list() +% has to take not the refernce count, but the first token. +% Passing def_ref, a next invocation of scan_toks() was inserting +% a missing left brace and then reading pass the end of the token +% list to find a matching right one. def_ref => link(def_ref). +% Test code narrowed down by Phelype Oleinik (a great help!). +% - The API for file related primitives has been changed: no error +% is reported on failure to find/open and nothing is returned +% (matches current other implementations). +% 0.99.9: +% - Fix typos in Pascal replacement text; xchg_buffer_length=0 => +% xchg_buffer_length:=0 (caught by Martin Ruckert). +% 0.99.10: +% - KerTeX Public License -> X11/MIT license. +% 1.0: +% - Just naming the official release. No change. +% +% This work was done by Thierry Laronde and is under the MIT/X11 +% license. +% +% + +% Here is TeX material that gets inserted after \input webmac +\def\hang{\hangindent 3em\noindent\ignorespaces} +\def\hangg#1 {\hang\hbox{#1 }} +\def\textindent#1{\hangindent2.5em\noindent\hbox to2.5em{\hss#1 }\ignorespaces} +\font\ninerm=cmr9 +\let\mc=\ninerm % medium caps for names like SAIL +\def\Prote{{\tenrm P\kern-0.1em R\kern-0.15em\raise.11ex\hbox{o}% + \kern-0.22em T\kern-0.05em E}} +\def\texprof{{\TeX}prof} +\ifpdftex +\sanitizecommand{\texprof}{TeXprof} +\sanitizecommand{\eTeX}{eTeX} +\sanitizecommand{\Prote}{PRoTE} +\fi +\font\tenlogo=logo10 +\def\MP{{\tenlogo META}\-{\tenlogo POST}} +\def\eTeX{$\varepsilon$-\TeX} +\font\revrm=xbmc10 % for right-to-left text +% to generate xbmc10 (i.e., reflected cmbx10) use a file +% xbmc10.mf containing: +%+++++++++++++++++++++++++++++++++++++++++++++++++ +% if unknown cmbase: input cmbase fi +% extra_endchar := extra_endchar & +% "currentpicture:=currentpicture " & +% "reflectedabout((.5[l,r],0),(.5[l,r],1));"; +% input cmbx10 +%+++++++++++++++++++++++++++++++++++++++++++++++++ +\ifx\beginL\undefined % this is TeX + \def\XeT{X\kern-.125em\lower.5ex\hbox{E}\kern-.1667emT} + \def\TeXeT{\TeX-\hbox{\revrm \XeT}} % for TeX-XeT + \def\TeXXeT{\TeX-\hbox{\revrm -\XeT}} % for TeX--XeT +\else + \ifx\eTeXversion\undefined % this is \TeXeT + \def\TeXeT{\TeX-{\revrm\beginR\TeX\endR}} % for TeX-XeT + \def\TeXXeT{\TeX-{\revrm\beginR\TeX-\endR}} % for TeX--XeT + \else % this is \eTeX + \def\TeXeT{\TeX-{\TeXXeTstate=1\revrm\beginR\TeX\endR}} % for TeX-XeT + \def\TeXXeT{\TeX-{\TeXXeTstate=1\revrm\beginR\TeX-\endR}} % for TeX--XeT + \fi +\fi +\def\PASCAL{Pascal} +\def\pdfTeX{pdf\TeX} +\def\ph{\hbox{Pascal-H}} +\def\pct!{{\char`\%}} % percent sign in ordinary text +\def\grp{\.{\char'173...\char'175}} +\font\logo=logo10 % font used for the METAFONT logo +\def\MF{{\logo META}\-{\logo FONT}} +\def\<#1>{$\langle#1\rangle$} +\def\section{\mathhexbox278} + +\def\(#1){} % this is used to make section names sort themselves better +\def\9#1{} % this is used for sort keys in the index via @@:sort key}{entry@@> + +\let\@@=\relax % we want to be able to \write a \? + +\def\title{\texprof} +\def\LaTeX{L\kern-.36em\raise.3ex\hbox{\sc A}\kern-.15em\TeX}% +% system dependent redefinitions of \title should come later +% and should use: +% \toks0=\expandafter{\title} +% \edef\title{...\the\toks0...} +%\let\maybe=\iffalse % print only changed modules +\def\topofcontents{\hsize 5.5in + \vglue 0pt plus 1fil minus 1.5in + \def\@@##1]{\hbox to 1in{\hfil##1.\ }} + } +\def\botofcontents{\vskip 0pt plus 1fil minus 1.5in} +\pageno=3 +\def\glob{13} % this should be the section number of "" +\def\gglob{20, 26} % this should be the next two sections of "" + +\def\.#1{\leavevmode\hbox{\tentex % typewriter type for strings + \let\\=\BS % backslash in a string + \let\'=\RQ % right quote in a string + \let\`=\LQ % left quote in a string + \let\{=\LB % left brace in a string + \let\}=\RB % right brace in a string + \let\~=\TL % tilde in a string + \let\ =\SP % space in a string + \let\_=\UL % underline in a string + \let\&=\AM % ampersand in a string + \let\^=\CF % circumflex in a string + #1\kern.05em}} +\def\{\leavevmode\hbox{\bf\def\_{\UL}% + #1\/\kern.05em}} % boldface type for reserved words +\def\\#1{\leavevmode\hbox{\it\def\_{\UL}% + #1\/\kern.05em}} % italic type for identifiers +\def\vb#1{{\rm #1}} +%\def\^{\ifmmode\mathchar"222 \else\char`^ \fi} % pointer or hat +\def\LQ{{\tt\char'22}} % left quote in a string +\def\RQ{{\tt\char'23}} % right quote in a string +\def\UL{{\tt\char`\_}} % underline character in a C identifier +\def\CF{{\tt\char`^}} +\def\dotdot{\mathrel{.\,.}} % double dot, used only in math mode +\setbox\MGbox=\hbox{\kern1pt$\rightarrow$\kern1pt} % C pointer to field +\def\MG{\copy\MGbox} +@s dotdot TeX +@s alpha_file int +@s byte_file int +@s word_file int +@s uint8_t int +@s int16_t int +@s uint16_t int +@s int32_t int +@s uint32_t int +@s halfword int +@s nonnegative_integer int +@s small_number int +@s glue_ratio double +@s Xdimen int +@s Kern int +@s Font int +@s Glue int +@s Disc int +@s Lig int +@s Rule int +@s List int +@s Kind int +@s Info int +@s kpse_file_format_type int +@s Stretch int +@s in TeX +@s line normal +@s to do + +@* Introduction. +This is \texprof, an implementation of \TeX\ with an extension providing profiling +capabilities. To be useful nowadays, the profiling capability is not the only +extension of Donald Knuth's original implementation of \TeX. + +To obtain the present \CEE/ program, Donald Knuth's \PASCAL\ program was +modified in a first step using most of the \eTeX\ extensions by +Peter Breitenlohner and Phil Taylor. +@^Breitenlohner, Peter@> +@^Taylor, Phil@> +Then further extensions were added using the \Prote\ change file +of Thierry Laronde. +@^Laronde, Thierry@> +Then the constants defining the size of \TeX's data structures, +notably the size of the |mem| array, were increased considerable. All these +changes to the \PASCAL\ program are necessary to run a current \LaTeX\ on the +resulting \TeX\ engine. The next important step was then to translate this +literate \PASCAL\ program to a literate \CEE/ program using the +{\tt web2w} source code translator. The use of the \CEE/ based \.{cweb} system +instead of the \PASCAL\ based \.{WEB} system greatly simplifies the tool chain +necessary for producing an executable program and allows true source level +debugging of the resulting program. The latter is indispensable to carry out +large scale modifications of the \TeX\ program and is of enormous help even +for smaller modifications. +The first modification of the resulting \CEE/ program was then the addition +of \CEE/ routines from the \TeX\ Live project to enable the use of the +kpath search library by Karl Berry. +@^Berry, Karl@> +The last and final step was the addition of profiling capabilities +which includes, as the latest addition, the definition of numerous +primitives that enable the \TeX\ profiler to pretend to be \pdfTeX. +The code used there reuses parts of the \CEE/ version of \pdfTeX\ by +H\`an Th\^e\llap{\raise 0.5ex\hbox{\'{}}} Th\`anh. +@^Th\`anh, H\`an Th\^e\llap{\raise 0.5ex\hbox{\'{}}}@> + +All these changes left their traces in the text that follows. +No attempt was made to streamline the text and rid it from the traces +of its exciting history. +So with the next paragraph you can start reading Donald Knuth's +introduction to his \TeX\ program. Enjoy! +\medskip + +This is \TeX, a document compiler intended to produce typesetting of high +quality. +The \PASCAL\ program that follows is the definition of \TeX82, a standard +@:PASCAL}{\PASCAL@> +@!@:TeX82}{\TeX82@> +version of \TeX\ that is designed to be highly portable so that identical output +will be obtainable on a great variety of computers. + +The main purpose of the following program is to explain the algorithms of \TeX\ +as clearly as possible. As a result, the program will not necessarily be very +efficient when a particular \PASCAL\ compiler has translated it into a +particular machine language. However, the program has been written so that it +can be tuned to run efficiently in a wide variety of operating environments +by making comparatively few changes. Such flexibility is possible because +the documentation that follows is written in the \.{WEB} language, which is +at a higher level than \PASCAL; the preprocessing step that converts \.{WEB} +to \PASCAL\ is able to introduce most of the necessary refinements. +Semi-automatic translation to other languages is also feasible, because the +program below does not make extensive use of features that are peculiar to +\PASCAL. + +A large piece of software like \TeX\ has inherent complexity that cannot +be reduced below a certain level of difficulty, although each individual +part is fairly simple by itself. The \.{WEB} language is intended to make +the algorithms as readable as possible, by reflecting the way the +individual program pieces fit together and by providing the +cross-references that connect different parts. Detailed comments about +what is going on, and about why things were done in certain ways, have +been liberally sprinkled throughout the program. These comments explain +features of the implementation, but they rarely attempt to explain the +\TeX\ language itself, since the reader is supposed to be familiar with +{\sl The \TeX book}. +@.WEB@> +@:TeXbook}{\sl The \TeX book@> + +@ The present implementation has a long ancestry, beginning in the summer +of~1977, when Michael~F. Plass and Frank~M. Liang designed and coded +a prototype +@^Plass, Michael Frederick@> +@^Liang, Franklin Mark@> +@^Knuth, Donald Ervin@> +based on some specifications that the author (in the following, unless +specified, ``the author'' refers to D.E.~Knuth) had made in May of that year. +This original proto\TeX\ included macro definitions and elementary +manipulations on boxes and glue, but it did not have line-breaking, +page-breaking, mathematical formulas, alignment routines, error recovery, +or the present semantic nest; furthermore, +it used character lists instead of token lists, so that a control sequence +like \.{\\halign} was represented by a list of seven characters. A +complete version of \TeX\ was designed and coded by the author in late +1977 and early 1978; that program, like its prototype, was written in the +{\mc SAIL} language, for which an excellent debugging system was +available. Preliminary plans to convert the {\mc SAIL} code into a form +somewhat like the present ``web'' were developed by Luis Trabb~Pardo and +@^Trabb Pardo, Luis Isidoro@> +the author at the beginning of 1979, and a complete implementation was +created by Ignacio~A. Zabala in 1979 and 1980. The \TeX82 program, which +@^Zabala Salelles, Ignacio Andr\'es@> +was written by the author during the latter part of 1981 and the early +part of 1982, also incorporates ideas from the 1979 implementation of +@^Guibas, Leonidas Ioannis@> +@^Sedgewick, Robert@> +@^Wyatt, Douglas Kirk@> +\TeX\ in {\mc MESA} that was written by Leonidas Guibas, Robert Sedgewick, +and Douglas Wyatt at the Xerox Palo Alto Research Center. Several hundred +refinements were introduced into \TeX82 based on the experiences gained with +the original implementations, so that essentially every part of the system +has been substantially improved. After the appearance of ``Version 0'' in +September 1982, this program benefited greatly from the comments of +many other people, notably David~R. Fuchs and Howard~W. Trickey. +A final revision in September 1989 extended the input character set to +eight-bit codes and introduced the ability to hyphenate words from +different languages, based on some ideas of Michael~J. Ferguson. +@^Fuchs, David Raymond@> +@^Trickey, Howard Wellington@> +@^Ferguson, Michael John@> + +No doubt there still is plenty of room for improvement, but the author +is firmly committed to keeping \TeX82 ``frozen'' from now on; stability +and reliability are to be its main virtues. + +On the other hand, the \.{WEB} description can be extended without changing +the core of \TeX82 itself, and the program has been designed so that such +extensions are not extremely difficult to make. +The |banner| string defined here should be changed whenever \TeX\ +undergoes any modifications, so that it will be clear which version of +\TeX\ might be the guilty party when a problem arises. +@^extensions to \TeX@> +@^system dependencies@> + +This program contains code for various features extending \TeX, +therefore this program is called `\Prote' and not +`\TeX'; the official name `\TeX' by itself is reserved +for software systems that are fully compatible with each other. +A special test suite called the ``\.{TRIP} test'' is available for +helping to determine whether a particular implementation deserves to be +known as `\TeX' [cf.~Stanford Computer Science report CS1027, +November 1984]. + +A similar test suite called the ``\.{SELLETTE} test'' is available for +helping to determine whether a particular implementation deserves to be +known as `\Prote'. + +@d eTeX_version 2 /* \.{\\eTeXversion} */ +@d eTeX_revision ".6" /* \.{\\eTeXrevision} */ +@d eTeX_version_string "-2.6" /*current \eTeX\ version*/ +@# +@d TeX_banner "This is TeX, Version 3.141592653" /*printed when \TeX\ starts*/ +@# +@# +@d TEX ETEX /*change program name into |ETEX|*/ +@# +@d eTeX_states 1 /*number of \eTeX\ state variables in |eqtb|*/ +@# +@d Prote_version_string "3.141592653-2.6-1.1.0" /*current \Prote\ version*/ +@d Prote_version 1 /* \.{\\Proteversion} */ +@d Prote_revision ".1.0" /* \.{\\Proterevision} */ +@# +@d Prote_banner "This is Prote, Version " Prote_version_string + /*printed when \Prote\ starts*/ +@# +@d banner Prote_banner + +@ Different \PASCAL s have slightly different conventions, and the present +@!@:PASCAL H}{\ph@> +program expresses \TeX\ in terms of the \PASCAL\ that was +available to the author in 1982. Constructions that apply to +this particular compiler, which we shall call \ph, should help the +reader see how to make an appropriate interface for other systems +if necessary. (\ph\ is Charles Hedrick's modification of a compiler +@^Hedrick, Charles Locke@> +for the DECsystem-10 that was originally developed at the University of +Hamburg; cf.\ {\sl Software---Practice and Experience \bf6} (1976), +29--42. The \TeX\ program below is intended to be adaptable, without +extensive changes, to most other versions of \PASCAL, so it does not fully +use the admirable features of \ph. Indeed, a conscious effort has been +made here to avoid using several idiosyncratic features of standard +\PASCAL\ itself, so that most of the code can be translated mechanically +into other high-level languages. For example, the `\&{with}' and `\\{new}' +features are not used, nor are pointer types, set types, or enumerated +scalar types; there are no `\&{var}' parameters, except in the case of files +--- \eTeX, however, does use `\&{var}' parameters for the |reverse| function; +there are no tag fields on variant records; there are no assignments +|double=int|; no procedures are declared local to other procedures.) + +The portions of this program that involve system-dependent code, where +changes might be necessary because of differences between \PASCAL\ compilers +and/or differences between +operating systems, can be identified by looking at the sections whose +numbers are listed under `system dependencies' in the index. Furthermore, +the index entries for `dirty \PASCAL' list all places where the restrictions +of \PASCAL\ have not been followed perfectly, for one reason or another. +@!@^system dependencies@> +@!@^dirty \PASCAL@> + +Incidentally, \PASCAL's standard |round| function can be problematical, +because it disagrees with the IEEE floating-point standard. +Many implementors have +therefore chosen to substitute their own home-grown rounding procedure. + +@ The following is an outline of the program, whose +components will be filled in later, using the conventions of \.{cweb}. +@.WEB@> +For example, the portion of the program called `\X\glob:Global +variables\X' below will be replaced by a sequence of variable declarations +that starts in $\section\glob$ of this documentation. In this way, we are able +to define each individual global variable when we are prepared to +understand what it means; we do not have to define all of the globals at +once. Cross references in $\section\glob$, where it says ``See also +sections \gglob, \dots,'' also make it possible to look at the set of +all global variables, if desired. Similar remarks apply to the other +portions of the program. + +The program starts with inserting header files and occassionaly a function +must be placed before declaring \TeX's macros, because the function +uses identifiers that \TeX will declare as macros. + +@p @
@; +@h +enum {@@; + @!empty_string=256 /*the empty string follows after 256 characters*/ +}; +@@; +@@; +@@; +@# +static void initialize(void) /*this procedure gets things started properly*/ + {@+@@; + @; + } @# +@@; +@@; + +@ The overall \TeX\ program begins with the heading just shown, after which +comes a bunch of procedure declarations and function declarations. +Finally we will get to the main program, which begins with the +comment `|start_here|'. If you want to skip down to the +main program now, you can look up `|start_here|' in the index. +But the author suggests that the best way to understand this program +is to follow pretty much the order of \TeX's components as they appear in the +\.{WEB} description you are now reading, since the present ordering is +intended to combine the advantages of the ``bottom up'' and ``top down'' +approaches to the problem of understanding a somewhat complicated system. + +@ There is no need to declare labels in \CEE/. + +@ Some of the code below is intended to be used only when diagnosing the +strange behavior that sometimes occurs when \TeX\ is being installed or +when system wizards are fooling around with \TeX\ without quite knowing +what they are doing. Such code will not normally be compiled; it is +delimited by the codewords `$|@t\#\&{ifdef} \.{DEBUG}@>|\ldots|@t\#\&{endif}@>|$', with apologies +to people who wish to preserve the purity of English. + +Similarly, there is some conditional code delimited by +`$|@t\#\&{ifdef} \.{STAT}@>|\ldots|@t\#\&{endif}@>|$' that is intended for use when statistics are to be +kept about \TeX's memory usage. The |@t\#\&{ifdef} \.{STAT}@>| $\ldots$ |@t\#\&{endif}@>| code also +implements diagnostic information for \.{\\tracingparagraphs}, +\.{\\tracingpages}, and \.{\\tracingrestores}. +@^debugging@> + +@ This program has two important variations: (1) There is a long and slow +version called \.{INITEX}, which does the extra calculations needed to +@.INITEX@> +initialize \TeX's internal tables; and (2)~there is a shorter and faster +production version, which cuts the initialization to a bare minimum. +Parts of the program that are needed in (1) but not in (2) are delimited by +the codewords `$|@t\#\&{ifdef} \.{INIT}@>|\ldots|@t\#\&{endif}@>|$'. + +\TeX\ Live has established the common practice +to select the initialization code at runtime +using the |iniversion| variable. + +@= +@@/ +#ifdef @!INIT +if (iniversion) /* \TeX\ Live*/ + {@+@@;@+} +#endif + +@ The declaration of the necessary type definitions are +contained in header files. + + +@
= +#include +#include +#include + +@ Further it is necessary to define some build in primitives of +\PASCAL\ that are otherwise not available in~\CEE/. +@:PASCAL H}{\ph@> + +@d odd(X) ((X)&1) +@d chr(X) ((unsigned char)(X)) +@d ord(X) ((unsigned int)(X)) +@d abs(X) ((X)>-(X)?(X):-(X)) +@d round(X) ((int)((X)>=0.0?floor((X)+0.5):ceil((X)-0.5))) + +@ The following parameters can be changed at compile time to extend or +reduce \TeX's capacity. They may have different values in \.{INITEX} and +in production versions of \TeX. +@.INITEX@> +@^system dependencies@> + +@= +@!mem_max=5000000, /*greatest index in \TeX's internal |mem| array; + must be strictly less than |max_halfword|; + must be equal to |mem_top| in \.{INITEX}, otherwise | >= mem_top|*/ +@!mem_min=0, /*smallest index in \TeX's internal |mem| array; + must be |min_halfword| or more; + must be equal to |mem_bot| in \.{INITEX}, otherwise | <= mem_bot|*/ +@!buf_size=2000000, /*maximum number of characters simultaneously present in + current lines of open files and in control sequences between + \.{\\csname} and \.{\\endcsname}; must not exceed |max_halfword|*/ +@!error_line=79, /*width of context lines on terminal error messages*/ +@!half_error_line=50, /*width of first lines of contexts in terminal + error messages; should be between 30 and |error_line-15|*/ +@!max_print_line=79, /*width of longest text lines output; should be at least 60*/ +@!stack_size=5000, /*maximum number of simultaneous input sources*/ +@!max_in_open=15, /*maximum number of input files and error insertions that + can be going on simultaneously*/ +@!font_max=255, /*maximum internal font number; must not exceed |max_quarterword| + and must be at most |font_base+256|*/ +@!font_mem_size=8000000, /*number of words of |font_info| for all fonts*/ +@!param_size=10000, /*maximum number of simultaneous macro parameters*/ +@!nest_size=500, /*maximum number of semantic levels simultaneously active*/ +@!max_strings=500000, /*maximum number of strings; must not exceed |max_halfword|*/ +@!string_vacancies=90000, /*the minimum number of characters that should be + available for the user's control sequences and font names, + after \TeX's own error messages are stored*/ +@!pool_size=6250000, /*maximum number of characters in strings, including all + error messages and help texts, and the names of all fonts and + control sequences; must exceed |string_vacancies| by the total + length of \TeX's own strings, which is currently about 23000*/ +@!save_size=100000, /*space for saving values outside of current group; must be + at most |max_halfword|*/ +@!trie_size=1000000, /*space for hyphenation patterns; should be larger for + \.{INITEX} than it is in production versions of \TeX*/ +@!trie_op_size=35111, /*space for ``opcodes'' in the hyphenation patterns*/ +@!dvi_buf_size=16384, /*size of the output buffer; must be a multiple of 8*/ +@!file_name_size=1024, /*file names shouldn't be longer than this*/ +@!xchg_buffer_size=64, /*must be at least 64*/ + /*size of |eight_bits| buffer for exchange with system routines*/ + +@ Like the preceding parameters, the following quantities can be changed +at compile time to extend or reduce \TeX's capacity. But if they are changed, +it is necessary to rerun the initialization program \.{INITEX} +@.INITEX@> +to generate new tables for the production \TeX\ program. +One can't simply make helter-skelter changes to the following constants, +since certain rather complex initialization +numbers are computed from them. They are defined here using +\.{WEB} macros, instead of being put into the above |enum| list in order to +emphasize this distinction. + +@d mem_bot 0 /*smallest index in the |mem| array dumped by \.{INITEX}; + must not be less than |mem_min|*/ +@d mem_top 5000000 /*largest index in the |mem| array dumped by \.{INITEX}; + must be substantially larger than |mem_bot| + and not greater than |mem_max|*/ +@d font_base 0 /*smallest internal font number; must not be less + than |min_quarterword|*/ +@d hash_size 45000 /*maximum number of control sequences; it should be at most + about |(mem_max-mem_min)/(double)10|*/ +@d hash_prime 35999 /*a prime number equal to about 85\pct! of |hash_size|*/ +@d hyph_size 8191 /*another prime; the number of \.{\\hyphenation} exceptions*/ +@^system dependencies@> + +@ In case somebody has inadvertently made bad settings of the ``constants,'' +\TeX\ checks them using a global variable called |bad|. + +This is the first of many sections of \TeX\ where global variables are +defined. + +@= +static int @!bad; /*is some ``constant'' wrong?*/ + +@ Later on we will say `\ignorespaces|if (mem_max >= max_halfword) bad=14|', +or something similar. (We can't do that until |max_halfword| has been defined.) + +@= +bad=0; +if ((half_error_line < 30)||(half_error_line > error_line-15)) bad=1; +if (max_print_line < 60) bad=2; +if (dvi_buf_size%8!=0) bad=3; +if (mem_bot+1100 > mem_top) bad=4; +if (hash_prime > hash_size) bad=5; +if (max_in_open >= 128) bad=6; +if (mem_top < 256+11) bad=7; /*we will want |null_list > 255|*/ + +@ Labels are given symbolic names by the following definitions, so that +occasional |goto| statements will be meaningful. We insert the label +`|end|' just before the `\ignorespaces|} |\unskip' of a procedure in +which we have used the `|goto end|' statement defined below; the label +`|restart|' is occasionally used at the very beginning of a procedure; and +the label `|reswitch|' is occasionally used just prior to a |case| +statement in which some cases change the conditions and we wish to branch +to the newly applicable case. Loops that are set up with the |loop| +construction defined below are commonly exited by going to `|done|' or to +`|found|' or to `|not_found|', and they are sometimes repeated by going to +`|resume|'. If two or more parts of a subroutine start differently but +end up the same, the shared code may be gathered together at +`|common_ending|'. + +Incidentally, this program never declares a label that isn't actually used, +because some fussy \PASCAL\ compilers will complain about redundant labels. + +@ Here are some macros for common programming idioms. + +@d incr(A) A=A+1 /*increase a variable by unity*/ +@d decr(A) A=A-1 /*decrease a variable by unity*/ +@d negate(A) A=-A /*change the sign of a variable*/ +@d loop @+while (true) @+ /*repeat over and over until a |goto| happens*/ +@f loop else + /*\.{WEB}'s |else| acts like `\ignorespaces|while true do|\unskip'*/ +@d do_nothing /*empty statement*/ +@d empty 0 /*symbolic name for a null constant*/ + +@* The character set. +In order to make \TeX\ readily portable to a wide variety of +computers, all of its input text is converted to an internal eight-bit +code that includes standard ASCII, the ``American Standard Code for +Information Interchange.'' This conversion is done immediately when each +character is read in. Conversely, characters are converted from ASCII to +the user's external representation just before they are output to a +text file. + +Such an internal code is relevant to users of \TeX\ primarily because it +governs the positions of characters in the fonts. For example, the +character `\.A' has ASCII code $65=0101$, and when \TeX\ typesets +this letter it specifies character number 65 in the current font. +If that font actually has `\.A' in a different position, \TeX\ doesn't +know what the real position is; the program that does the actual printing from +\TeX's device-independent files is responsible for converting from ASCII to +a particular font encoding. +@^ASCII code@> + +\TeX's internal code also defines the value of constants +that begin with a reverse apostrophe; and it provides an index to the +\.{\\catcode}, \.{\\mathcode}, \.{\\uccode}, \.{\\lccode}, and \.{\\delcode} +tables. + +@ Characters of text that have been converted to \TeX's internal form +are said to be of type |ASCII_code|, which is a subrange of the integers. + +@= +typedef uint8_t ASCII_code; /*eight-bit numbers*/ + +@ The original \PASCAL\ compiler was designed in the late 60s, when six-bit +character sets were common, so it did not make provision for lowercase +letters. Nowadays, of course, we need to deal with both capital and small +letters in a convenient way, especially in a program for typesetting; +so the present specification of \TeX\ has been written under the assumption +that the \PASCAL\ compiler and run-time system permit the use of text files +with more than 64 distinguishable characters. More precisely, we assume that +the character set contains at least the letters and symbols associated +with ASCII codes 040 through 0176; all of these characters are now +available on most computer terminals. + +Since we are dealing with more characters than were present in the first +\PASCAL\ compilers, we have to decide what to call the associated data +type. Some \PASCAL s use the original name |unsigned char| for the +characters in text files, even though there now are more than 64 such +characters, while other \PASCAL s consider |unsigned char| to be a 64-element +subrange of a larger data type that has some other name. + +In order to accommodate this difference, we shall use the name |text_char| +to stand for the data type of the characters that are converted to and +from |ASCII_code| when they are input and output. We shall also assume +that |text_char| consists of the elements |chr(first_text_char)| through +|chr(last_text_char)|, inclusive. The following definitions should be +adjusted if necessary. +@^system dependencies@> + +@s text_char char +@d text_char unsigned char /*the data type of characters in text files*/ +@d first_text_char 0 /*ordinal number of the smallest element of |text_char|*/ +@d last_text_char 255 /*ordinal number of the largest element of |text_char|*/ + +@= +int @!i; + +@ The \TeX\ processor converts between ASCII code and +the user's external character set by means of arrays |xord| and |xchr| +that are analogous to \PASCAL's |ord| and |chr| functions. + +@= +static ASCII_code @!xord[256]; + /*specifies conversion of input characters*/ +static text_char @!xchr[256]; + /*specifies conversion of output characters*/ + +@ Since we are assuming that our \PASCAL\ system is able to read and +write the visible characters of standard ASCII (although not +necessarily using the ASCII codes to represent them), the following +assignment statements initialize the standard part of the |xchr| array +properly, without needing any system-dependent changes. On the other +hand, it is possible to implement \TeX\ with less complete character +sets, and in such cases it will be necessary to change something here. +@^system dependencies@> + +@= +xchr[040]=' '; +xchr[041]='!'; +xchr[042]='"'; +xchr[043]='#'; +xchr[044]='$'; +xchr[045]='%'; +xchr[046]='&'; +xchr[047]='\'';@/ +xchr[050]='('; +xchr[051]=')'; +xchr[052]='*'; +xchr[053]='+'; +xchr[054]=','; +xchr[055]='-'; +xchr[056]='.'; +xchr[057]='/';@/ +xchr[060]='0'; +xchr[061]='1'; +xchr[062]='2'; +xchr[063]='3'; +xchr[064]='4'; +xchr[065]='5'; +xchr[066]='6'; +xchr[067]='7';@/ +xchr[070]='8'; +xchr[071]='9'; +xchr[072]=':'; +xchr[073]=';'; +xchr[074]='<'; +xchr[075]='='; +xchr[076]='>'; +xchr[077]='?';@/ +xchr[0100]='@@'; +xchr[0101]='A'; +xchr[0102]='B'; +xchr[0103]='C'; +xchr[0104]='D'; +xchr[0105]='E'; +xchr[0106]='F'; +xchr[0107]='G';@/ +xchr[0110]='H'; +xchr[0111]='I'; +xchr[0112]='J'; +xchr[0113]='K'; +xchr[0114]='L'; +xchr[0115]='M'; +xchr[0116]='N'; +xchr[0117]='O';@/ +xchr[0120]='P'; +xchr[0121]='Q'; +xchr[0122]='R'; +xchr[0123]='S'; +xchr[0124]='T'; +xchr[0125]='U'; +xchr[0126]='V'; +xchr[0127]='W';@/ +xchr[0130]='X'; +xchr[0131]='Y'; +xchr[0132]='Z'; +xchr[0133]='['; +xchr[0134]='\\'; +xchr[0135]=']'; +xchr[0136]='^'; +xchr[0137]='_';@/ +xchr[0140]='`'; +xchr[0141]='a'; +xchr[0142]='b'; +xchr[0143]='c'; +xchr[0144]='d'; +xchr[0145]='e'; +xchr[0146]='f'; +xchr[0147]='g';@/ +xchr[0150]='h'; +xchr[0151]='i'; +xchr[0152]='j'; +xchr[0153]='k'; +xchr[0154]='l'; +xchr[0155]='m'; +xchr[0156]='n'; +xchr[0157]='o';@/ +xchr[0160]='p'; +xchr[0161]='q'; +xchr[0162]='r'; +xchr[0163]='s'; +xchr[0164]='t'; +xchr[0165]='u'; +xchr[0166]='v'; +xchr[0167]='w';@/ +xchr[0170]='x'; +xchr[0171]='y'; +xchr[0172]='z'; +xchr[0173]='{'; +xchr[0174]='|'; +xchr[0175]='}'; +xchr[0176]='~';@/ + +@ Some of the ASCII codes without visible characters have been given symbolic +names in this program because they are used with a special meaning. + +@d null_code 00 /*ASCII code that might disappear*/ +@d carriage_return 015 /*ASCII code used at end of line*/ +@d invalid_code 0177 /*ASCII code that many systems prohibit in text files*/ + +@ The ASCII code is ``standard'' only to a certain extent, since many +computer installations have found it advantageous to have ready access +to more than 94 printing characters. Appendix~C of {\sl The \TeX book\/} +gives a complete specification of the intended correspondence between +characters and \TeX's internal representation. +@:TeXbook}{\sl The \TeX book@> + +If \TeX\ is being used +on a garden-variety \PASCAL\ for which only standard ASCII +codes will appear in the input and output files, it doesn't really matter +what codes are specified in |xchr[0 dotdot 037]|, but the safest policy is to +blank everything out by using the code shown below. + +However, other settings of |xchr| will make \TeX\ more friendly on +computers that have an extended character set, so that users can type things +like `\.^^Z' instead of `\.{\\ne}'. People with extended character sets can +assign codes arbitrarily, giving an |xchr| equivalent to whatever +characters the users of \TeX\ are allowed to have in their input files. +It is best to make the codes correspond to the intended interpretations as +shown in Appendix~C whenever possible; but this is not necessary. For +example, in countries with an alphabet of more than 26 letters, it is +usually best to map the additional letters into codes less than~040. +To get the most ``permissive'' character set, change |' '| on the +right of these assignment statements to |chr(i)|. +@^character set dependencies@> +@^system dependencies@> + +@= +for (i=0; i<=037; i++) xchr[i]=chr(i); /* \TeX\ Live*/ +for (i=0177; i<=0377; i++) xchr[i]=chr(i); /* \TeX\ Live*/ + +@ The following system-independent code makes the |xord| array contain a +suitable inverse to the information in |xchr|. Note that if |xchr[i]==xchr[j]| +where |i < j < 0177|, the value of |xord[xchr[i]]| will turn out to be +|j| or more; hence, standard ASCII code numbers will be used instead of +codes below 040 in case there is a coincidence. + +@= +for (i=first_text_char; i<=last_text_char; i++) xord[chr(i)]=invalid_code; +for (i=0200; i<=0377; i++) xord[xchr[i]]=i; +for (i=0; i<=0176; i++) xord[xchr[i]]=i; + +@* Input and output. +The bane of portability is the fact that different operating systems treat +input and output quite differently, perhaps because computer scientists +have not given sufficient attention to this problem. People have felt somehow +that input and output are not part of ``real'' programming. Well, it is true +that some kinds of programming are more fun than others. With existing +input/output conventions being so diverse and so messy, the only sources of +joy in such parts of the code are the rare occasions when one can find a +way to make the program a little less bad than it might have been. We have +two choices, either to attack I/O now and get it over with, or to postpone +I/O until near the end. Neither prospect is very attractive, so let's +get it over with. + +The basic operations we need to do are (1)~inputting and outputting of +text, to or from a file or the user's terminal; (2)~inputting and +outputting of eight-bit bytes, to or from a file; (3)~instructing the +operating system to initiate (``open'') or to terminate (``close'') input or +output from a specified file; (4)~testing whether the end of an input +file has been reached. + +\TeX\ needs to deal with two kinds of files. +We shall use the term |alpha_file| for a file that contains textual data, +and the term |byte_file| for a file that contains eight-bit binary information. +These two types turn out to be the same on many computers, but +sometimes there is a significant distinction, so we shall be careful to +distinguish between them. Standard protocols for transferring +such files from computer to computer, via high-speed networks, are +now becoming available to more and more communities of users. + +The program actually makes use also of a third kind of file, called a +|word_file|, when dumping and reloading base information for its own +initialization. We shall define a word file later; but it will be possible +for us to specify simple operations on word files before they are defined. + +@= +typedef uint8_t eight_bits; /*unsigned one-byte quantity*/ +typedef struct {@+FILE *f;@+text_char@,d;@+} alpha_file; /*files that contain textual data*/ +typedef struct {@+FILE *f;@+eight_bits@,d;@+} byte_file; /*files that contain binary data*/ + +@ Most of what we need to do with respect to input and output can be handled +by the I/O facilities that are standard in \PASCAL, i.e., the routines +called |get|, |put|, |eof|, and so on. But +standard \PASCAL\ does not allow file variables to be associated with file +names that are determined at run time, so it cannot be used to implement +\TeX; some sort of extension to \PASCAL's ordinary |reset| and |rewrite| +is crucial for our purposes. We shall assume that |name_of_file| is a variable +of an appropriate type such that the \PASCAL\ run-time system being used to +implement \TeX\ can open a file whose external name is specified by +|name_of_file|. +@^system dependencies@> + +@= +static unsigned char @!name_of_file0[file_name_size+1]={0}, + *const @!name_of_file = @!name_of_file0-1;@;@/ + /*on some systems this may be a \&{record} variable*/ +static int @!name_length;@/ /*this many characters are actually + relevant in |name_of_file| (the rest are blank)*/ + +@ To open files, \TeX\ used \PASCAL's |reset| function. +We use the {\tt kpathsearch} library to implement new functions +in the section on \TeX\ Live Integration. +Here we give only the function prototypes. + +\TeX's file-opening functions do not issue their own +error messages if something goes wrong. If a file identified by +|name_of_file| cannot be found, +or if such a file cannot be opened for some other reason +(e.g., someone may already be trying to write the same file) +\TeX's file-opening functions return |false|. +This allows \TeX\ to undertake appropriate corrective action. +@^system dependencies@> + +@p +static FILE*open_in(char*filename,kpse_file_format_type t,const char*rwb); /* \TeX\ Live*/ +static bool a_open_in(alpha_file *f); /*open a text file for input*/ +static bool b_open_in(byte_file *f); /*open a binary file for input*/ +static bool w_open_in(word_file *f); /*open a word file for input*/ +static FILE *open_out(const char *file_name, const char *file_mode); /* \TeX\ Live*/ +static bool a_open_out(alpha_file *f); /*open a text file for output*/ +static bool b_open_out(byte_file *f); /*open a binary file for output*/ +#ifdef @!INIT +static bool w_open_out(word_file *f); /*open a word file for output*/ +#endif + +@ Files can be closed with the \ph\ routine `|pascal_close(f)|', which +@:PASCAL H}{\ph@> +@^system dependencies@> +should be used when all input or output with respect to |f| has been completed. +This makes |f| available to be opened again, if desired; and if |f| was used for +output, the |pascal_close| operation makes the corresponding external file appear +on the user's area, ready to be read. + +These procedures should not generate error messages if a file is +being closed before it has been successfully opened. + +@p static void a_close(alpha_file *f) /*close a text file*/ +{@+pascal_close((*f)); +} +@# +static void b_close(byte_file *f) /*close a binary file*/ +{@+pascal_close((*f)); +} +@# +static void w_close(word_file *f) /*close a word file*/ +{@+pascal_close((*f)); +} + +@ Binary input and output are done with \PASCAL's ordinary |get| and |put| +procedures, so we don't have to make any other special arrangements for +binary~I/O. Text output is also easy to do with standard \PASCAL\ routines. +The treatment of text input is more difficult, however, because +of the necessary translation to |ASCII_code| values. +\TeX's conventions should be efficient, and they should +blend nicely with the user's operating environment. + +@ Input from text files is read one line at a time, using a routine called +|input_ln|. This function is defined in terms of global variables called +|buffer|, |first|, and |last| that will be described in detail later; for +now, it suffices for us to know that |buffer| is an array of |ASCII_code| +values, and that |first| and |last| are indices into this array +representing the beginning and ending of a line of text. + +@= +static ASCII_code @!buffer[buf_size+1]; /*lines of characters being read*/ +static int @!first; /*the first unused position in |buffer|*/ +static int @!last; /*end of the line just input to |buffer|*/ +static int @!max_buf_stack; /*largest index used in |buffer|*/ + +@ The |input_ln| function brings the next line of input from the specified +file into available positions of the buffer array and returns the value +|true|, unless the file has already been entirely read, in which case it +returns |false| and sets |last=first|. In general, the |ASCII_code| +numbers that represent the next line of the file are input into +|buffer[first]|, |buffer[first+1]|, \dots, |buffer[last-1]|; and the +global variable |last| is set equal to |first| plus the length of the +line. Trailing blanks are removed from the line; thus, either |last==first| +(in which case the line was entirely blank) or |buffer[last-1]!=' '|. + +An overflow error is given, however, if the normal actions of |input_ln| +would make |last >= buf_size|; this is done so that other parts of \TeX\ +can safely look at the contents of |buffer[last+1]| without overstepping +the bounds of the |buffer| array. Upon entry to |input_ln|, the condition +|first < buf_size| will always hold, so that there is always room for an +``empty'' line. + +The variable |max_buf_stack|, which is used to keep track of how large +the |buf_size| parameter must be to accommodate the present job, is +also kept up to date by |input_ln|. + +If the |bypass_eoln| parameter is |true|, |input_ln| will do a |get| +before looking at the first character of the line; this skips over +an |eoln| that was in |f.d|. The procedure does not do a |get| when it +reaches the end of the line; therefore it can be used to acquire input +from the user's terminal as well as from ordinary text files. + +Standard \PASCAL\ says that a file should have |eoln| immediately +before |eof|, but \TeX\ needs only a weaker restriction: If |eof| +occurs in the middle of a line, the system function |eoln| should return +a |true| result (even though |f.d| will be undefined). + +Since the inner loop of |input_ln| is part of \TeX's ``inner loop''---each +character of input comes in at this place---it is wise to reduce system +overhead by making use of special routines that read in an entire array +of characters at once, if such routines are available. The following +code uses standard \PASCAL\ to illustrate what needs to be done, but +finer tuning is often possible at well-developed \PASCAL\ sites. +@^inner loop@> + +@p static bool input_ln(alpha_file *f, bool @!bypass_eoln) + /*inputs the next line or returns |false|*/ +{@+int last_nonblank; /*|last| with trailing blanks removed*/ +if (bypass_eoln) if (!eof((*f))) get((*f)); + /*input the first character of the line into |f.d|*/ +last=first; /*cf.\ Matthew 19\thinspace:\thinspace30*/ +if (eof((*f))) return false; +else{@+last_nonblank=first; + while (!eoln((*f))) + {@+if (last >= max_buf_stack) + {@+max_buf_stack=last+1; + if (max_buf_stack==buf_size) + @; + } + buffer[last]=xord[(*f).d];get((*f));incr(last); + if (buffer[last-1]!=' ') last_nonblank=last; + } + last=last_nonblank;return true; + } +} + +@ The user's terminal acts essentially like other files of text, except +that it is used both for input and for output. When the terminal is +considered an input file, the file variable is called |term_in|, and when it +is considered an output file the file variable is |term_out|. +@^system dependencies@> + +@= +static alpha_file @!term_in; /*the terminal as an input file*/ +static alpha_file @!term_out; /*the terminal as an output file*/ + +@ Here is how to open the terminal files +in \ph. The `\.{/I}' switch suppresses the first |get|. +@:PASCAL H}{\ph@> +@^system dependencies@> + +@d t_open_in term_in.f=stdin /*open the terminal for text input*/ +@d t_open_out term_out.f=stdout /*open the terminal for text output*/ + +@ Sometimes it is necessary to synchronize the input/output mixture that +happens on the user's terminal, and three system-dependent +procedures are used for this +purpose. The first of these, |update_terminal|, is called when we want +to make sure that everything we have output to the terminal so far has +actually left the computer's internal buffers and been sent. +The second, |clear_terminal|, is called when we wish to cancel any +input that the user may have typed ahead (since we are about to +issue an unexpected error message). The third, |wake_up_terminal|, +is supposed to revive the terminal if the user has disabled it by +some instruction to the operating system. The following macros show how +these operations can be specified in \ph: +@:PASCAL H}{\ph@> +@^system dependencies@> + +@d update_terminal fflush(term_out.f) /*empty the terminal output buffer*/ +@d clear_terminal fflush(term_in.f) /*clear the terminal input buffer*/ +@d wake_up_terminal do_nothing /*cancel the user's cancellation of output*/ + +@ We need a special routine to read the first line of \TeX\ input from +the user's terminal. This line is different because it is read before we +have opened the transcript file; there is sort of a ``chicken and +egg'' problem here. If the user types `\.{\\input paper}' on the first +line, or if some macro invoked by that line does such an \.{\\input}, +the transcript file will be named `\.{paper.log}'; but if no \.{\\input} +commands are performed during the first line of terminal input, the transcript +file will acquire its default name `\.{texput.log}'. (The transcript file +will not contain error messages generated by the first line before the +first \.{\\input} command.) +@.texput@> + +The first line is even more special if we are lucky enough to have an operating +system that treats \TeX\ differently from a run-of-the-mill \PASCAL\ object +program. It's nice to let the user start running a \TeX\ job by typing +a command line like `\.{tex paper}'; in such a case, \TeX\ will operate +as if the first line of input were `\.{paper}', i.e., the first line will +consist of the remainder of the command line, after the part that invoked +\TeX. + +The first line is special also because it may be read before \TeX\ has +input a format file. In such cases, normal error messages cannot yet +be given. The following code uses concepts that will be explained later. +(If the \PASCAL\ compiler does not support non-local |@!goto|\unskip, the +@^system dependencies@> +statement `|goto exit(0)|' should be replaced by something that +quietly terminates the program.) + +@= +if (format_ident==0) + {@+write_ln(term_out,"Buffer size exceeded!");exit(0); +@.Buffer size exceeded@> + } +else{@+cur_input.loc_field=first;cur_input.limit_field=last-1; + overflow("buffer size", buf_size); +@:TeX capacity exceeded buffer size}{\quad buffer size@> + } + +@ Different systems have different ways to get started. But regardless of +what conventions are adopted, the routine that initializes the terminal +should satisfy the following specifications: + +\yskip\textindent{1)}It should open file |term_in| for input from the + terminal. (The file |term_out| will already be open for output to the + terminal.) + +\textindent{2)}If the user has given a command line, this line should be + considered the first line of terminal input. Otherwise the + user should be prompted with `\.{**}', and the first line of input + should be whatever is typed in response. + +\textindent{3)}The first line of input, which might or might not be a + command line, should appear in locations |first| to |last-1| of the + |buffer| array. + +\textindent{4)}The global variable |loc| should be set so that the + character to be read next by \TeX\ is in |buffer[loc]|. This + character should not be blank, and we should have |loc < last|. + +\yskip\noindent(It may be necessary to prompt the user several times +before a non-blank line comes in. The prompt is `\.{**}' instead of the +later `\.*' because the meaning is slightly different: `\.{\\input}' need +not be typed immediately after~`\.{**}'.) + +@d loc cur_input.loc_field /*location of first unread character in |buffer|*/ + +@ The following routine calls |input_command_line| +to retrieve a possible command line. +@^system dependencies@> + +@p static bool init_terminal(void) /*gets the terminal input started*/ +{@+ +t_open_in; +if (input_command_line()) return true; /* \TeX\ Live */ +loop@+{@+wake_up_terminal;pascal_write(term_out,"**");update_terminal; +@.**@> + if (!input_ln(&term_in, true)) /*this shouldn't happen*/ + {@+write_ln(term_out); + pascal_write(term_out,"! End of file on the terminal... why?"); +@.End of file on the terminal@> + return false; + } + loc=first; + while ((loc < last)&&(buffer[loc]==' ')) incr(loc); + if (loc < last) + {@+return true; + /*return unless the line was all blank*/ + } + write_ln(term_out,"Please type the name of your input file."); + } +} + +@* String handling. +Control sequence names and diagnostic messages are variable-length strings +of eight-bit characters. Since \PASCAL\ does not have a well-developed string +mechanism, \TeX\ does all of its string processing by homegrown methods. + +Elaborate facilities for dynamic strings are not needed, so all of the +necessary operations can be handled with a simple data structure. +The array |str_pool| contains all of the (eight-bit) ASCII codes in all +of the strings, and the array |str_start| contains indices of the starting +points of each string. Strings are referred to by integer numbers, so that +string number |s| comprises the characters |str_pool[j]| for +|str_start[s] <= j < str_start[s+1]|. Additional integer variables +|pool_ptr| and |str_ptr| indicate the number of entries used so far +in |str_pool| and |str_start|, respectively; locations +|str_pool[pool_ptr]| and |str_start[str_ptr]| are +ready for the next string to be allocated. + +String numbers 0 to 255 are reserved for strings that correspond to single +ASCII characters. This is in accordance with the conventions of \.{WEB}, +@.WEB@> +which converts single-character strings into the ASCII code number of the +single character involved, while it converts other strings into integers +and builds a string pool file. Thus, when the string constant \.{"."} appears +in the program below, \.{WEB} converts it into the integer 46, which is the +ASCII code for a period, while \.{WEB} will convert a string like \.{"hello"} +into some integer greater than~255. String number 46 will presumably be the +single character `\..'; but some ASCII codes have no standard visible +representation, and \TeX\ sometimes needs to be able to print an arbitrary +ASCII character, so the first 256 strings are used to specify exactly what +should be printed for each of the 256 possibilities. + +Elements of the |str_pool| array must be ASCII codes that can actually +be printed; i.e., they must have an |xchr| equivalent in the local +character set. (This restriction applies only to preloaded strings, +not to those generated dynamically by the user.) + +Some \PASCAL\ compilers won't pack integers into a single byte unless the +integers lie in the range |-128 dotdot 127|. To accommodate such systems +we access the string pool only via macros that can easily be redefined. +@^system dependencies@> + +@d si(A) A /*convert from |ASCII_code| to |packed_ASCII_code|*/ +@d so(A) A /*convert from |packed_ASCII_code| to |ASCII_code|*/ + +@= +typedef int32_t pool_pointer; /*for variables that point into |str_pool|*/ +typedef int32_t str_number; /*for variables that point into |str_start|*/ +typedef uint8_t packed_ASCII_code; /*elements of |str_pool| array*/ + +@ @= +static packed_ASCII_code @!str_pool[pool_size+1]; /*the characters*/ +static pool_pointer @!str_start[max_strings+1]; /*the starting pointers*/ +static pool_pointer @!pool_ptr; /*first unused position in |str_pool|*/ +static str_number @!str_ptr; /*number of the current string being created*/ +static pool_pointer @!init_pool_ptr; /*the starting value of |pool_ptr|*/ +static str_number @!init_str_ptr; /*the starting value of |str_ptr|*/ + +@ Several of the elementary string operations are performed using \.{WEB} +macros instead of \PASCAL\ procedures, because many of the +operations are done quite frequently and we want to avoid the +overhead of procedure calls. For example, here is +a simple macro that computes the length of a string. +@.WEB@> + +@d length(A) (str_start[A+1]-str_start[A]) /*the number of characters + in string number \#*/ + +@ The length of the current string is called |cur_length|: + +@d cur_length (pool_ptr-str_start[str_ptr]) + +@ Strings are created by appending character codes to |str_pool|. +The |append_char| macro, defined here, does not check to see if the +value of |pool_ptr| has gotten too high; this test is supposed to be +made before |append_char| is used. There is also a |flush_char| +macro, which erases the last character appended. + +To test if there is room to append |l| more characters to |str_pool|, +we shall write |str_room(l)|, which aborts \TeX\ and gives an +apologetic error message if there isn't enough room. + +@d append_char(A) /*put |ASCII_code| \# at the end of |str_pool|*/ +{@+str_pool[pool_ptr]=si(A);incr(pool_ptr); +} +@d flush_char decr(pool_ptr) /*forget the last character in the pool*/ +@d str_room(A) /*make sure that the pool hasn't overflowed*/ + {@+if (pool_ptr+A > pool_size) + overflow("pool size", pool_size-init_pool_ptr); +@:TeX capacity exceeded pool size}{\quad pool size@> + } + +@ Once a sequence of characters has been appended to |str_pool|, it +officially becomes a string when the function |make_string| is called. +This function returns the identification number of the new string as its +value. + +@p static str_number make_string(void) /*current string enters the pool*/ +{@+if (str_ptr==max_strings) + overflow("number of strings", max_strings-init_str_ptr); +@:TeX capacity exceeded number of strings}{\quad number of strings@> +incr(str_ptr);str_start[str_ptr]=pool_ptr; +return str_ptr-1; +} + +@ To destroy the most recently made string, we say |flush_string|. + +@d flush_string {@+decr(str_ptr);pool_ptr=str_start[str_ptr]; + } + +@ The following subroutine compares string |s| with another string of the +same length that appears in |buffer| starting at position |k|; +the result is |true| if and only if the strings are equal. +Empirical tests indicate that |str_eq_buf| is used in such a way that +it tends to return |true| about 80 percent of the time. + +@p static bool str_eq_buf(str_number @!s, int @!k) + /*test equality of strings*/ +{@+ /*loop exit*/ +pool_pointer j; /*running index*/ +bool @!result; /*result of comparison*/ +j=str_start[s]; +while (j < str_start[s+1]) + {@+if (so(str_pool[j])!=buffer[k]) + {@+result=false;goto not_found; + } + incr(j);incr(k); + } +result=true; +not_found: return result; +} + +@ Here is a similar routine, but it compares two strings in the string pool, +and it does not assume that they have the same length. + +@p static bool str_eq_str(str_number @!s, str_number @!t) + /*test equality of strings*/ +{@+ /*loop exit*/ +pool_pointer j, @!k; /*running indices*/ +bool @!result; /*result of comparison*/ +result=false; +if (length(s)!=length(t)) goto not_found; +j=str_start[s];k=str_start[t]; +while (j < str_start[s+1]) + {@+if (str_pool[j]!=str_pool[k]) goto not_found; + incr(j);incr(k); + } +result=true; +not_found: return result; +} +@t\4@>@@; + +@ The initial values of |str_pool|, |str_start|, |pool_ptr|, +and |str_ptr| are computed by the \.{INITEX} program, based in part +on the information that \.{WEB} has output while processing \TeX. +@.INITEX@> +@^string pool@> + +@p +static bool get_strings_started(void) /*initializes the string pool*/ +{@+ +int k, @!l; /*small indices or counters*/ +pool_ptr=0;str_ptr=0;str_start[0]=0; +@; +@; +return true; +} + +@ @d app_lc_hex(A) l=A; + if (l < 10) append_char(l+'0')@;@+else append_char(l-10+'a') + +@= +for (k=0; k<=255; k++) + {@+if ((@)) + {@+append_char('^');append_char('^'); + if (k < 0100) append_char(k+0100)@; + else if (k < 0200) append_char(k-0100)@; + else{@+app_lc_hex(k/16);app_lc_hex(k%16); + } + } + else append_char(k); + make_string(); + } + +@ The first 128 strings will contain 95 standard ASCII characters, and the +other 33 characters will be printed in three-symbol form like `\.{\^\^A}' +unless a system-dependent change is made here. Installations that have +an extended character set, where for example |xchr[032]==@t\.{\'^^Z\'}@>|, +would like string 032 to be the single character 032 instead of the +three characters 0136, 0136, 0132 (\.{\^\^Z}). On the other hand, +even people with an extended character set will want to represent string +015 by \.{\^\^M}, since 015 is |carriage_return|; the idea is to +produce visible strings instead of tabs or line-feeds or carriage-returns +or bell-rings or characters that are treated anomalously in text files. + +Unprintable characters of codes 128--255 are, similarly, rendered +\.{\^\^80}--\.{\^\^ff}. + +The boolean expression defined here should be |true| unless \TeX\ +internal code number~|k| corresponds to a non-troublesome visible +symbol in the local character set. An appropriate formula for the +extended character set recommended in {\sl The \TeX book\/} would, for +example, be `|k in[0, 010 dotdot 012, 014, 015, 033, 0177 dotdot 0377]|'. +If character |k| cannot be printed, and |k < 0200|, then character |k+0100| or +|k-0100| must be printable; moreover, ASCII codes |[041 dotdot 046, +060 dotdot 071, 0136, 0141 dotdot 0146, 0160 dotdot 0171]| must be printable. +Thus, at least 80 printable characters are needed. +@:TeXbook}{\sl The \TeX book@> +@^character set dependencies@> +@^system dependencies@> + +@= + (k < ' ')||(k > '~') + +@ The |pool_file| variable is no longer needed and has been removed. + +Instead of reading the other strings from the \.{TEX.POOL} file, +it is sufficient here to add the empty string. +@= +make_string(); + +@ Without a string pool file there is no need for a pool check sum either. +But this is a convenient place to define the function |s_no| that will +add literal strings to the string pool at runtime, thereby obtaining their +string number. + +@p static int s_no(const char *str) +{@+ + if (str[0]==0) return empty_string; + if (str[1]==0) return str[0]; + str_room(strlen(str)); + while (*str!=0) append_char(*str++); + return make_string(); +} + +@ The function |s_no| is used in |initialize| and needs a forward +declaration. + +@= +static int s_no(const char *str); + +@* On-line and off-line printing. +Messages that are sent to a user's terminal and to the transcript-log file +are produced by several `|print|' procedures. These procedures will +direct their output to a variety of places, based on the setting of +the global variable |selector|, which has the following possible +values: + +\yskip +\hang |term_and_log|, the normal setting, prints on the terminal and on the + transcript file. + +\hang |log_only|, prints only on the transcript file. + +\hang |term_only|, prints only on the terminal. + +\hang |no_print|, doesn't print at all. This is used only in rare cases + before the transcript file is open. + +\hang |pseudo|, puts output into a cyclic buffer that is used + by the |show_context| routine; when we get to that routine we shall discuss + the reasoning behind this curious mode. + +\hang |new_string|, appends the output to the current string in the + string pool. + +\hang 0 to 15, prints on one of the sixteen files for \.{\\write} output. + +\yskip +\noindent The symbolic names `|term_and_log|', etc., have been assigned +numeric codes that satisfy the convenient relations |no_print+1==term_only|, +|no_print+2==log_only|, |term_only+2==log_only+1==term_and_log|. + +Three additional global variables, |tally| and |term_offset| and +|file_offset|, record the number of characters that have been printed +since they were most recently cleared to zero. We use |tally| to record +the length of (possibly very long) stretches of printing; |term_offset| +and |file_offset|, on the other hand, keep track of how many characters +have appeared so far on the current line that has been output to the +terminal or to the transcript file, respectively. + +@d no_print 16 /*|selector| setting that makes data disappear*/ +@d term_only 17 /*printing is destined for the terminal only*/ +@d log_only 18 /*printing is destined for the transcript file only*/ +@d term_and_log 19 /*normal |selector| setting*/ +@d pseudo 20 /*special |selector| setting for |show_context|*/ +@d new_string 21 /*printing is deflected to the string pool*/ +@d max_selector 21 /*highest selector setting*/ + +@= +static alpha_file @!log_file; /*transcript of \TeX\ session*/ +static int @!selector; /*where to print a message*/ +static int8_t @!dig[23]; /*digits in a number being output*/ +static int @!tally; /*the number of characters recently printed*/ +static int @!term_offset; + /*the number of characters on the current terminal line*/ +static int @!file_offset; + /*the number of characters on the current file line*/ +static ASCII_code @!trick_buf[error_line+1]; /*circular buffer for + pseudoprinting*/ +static int @!trick_count; /*threshold for pseudoprinting, explained later*/ +static int @!first_count; /*another variable for pseudoprinting*/ + +@ @= +selector=term_only;tally=0;term_offset=0;file_offset=0; + +@ Macro abbreviations for output to the terminal and to the log file are +defined here for convenience. Some systems need special conventions +for terminal output, and it is possible to adhere to those conventions +by changing |wterm|, |wterm_ln|, and |wterm_cr| in this section. +@^system dependencies@> + +@= +#define @[put(F)@] @[fwrite(&((F).d)@],@[sizeof((F).d),1,(F).f)@]@; +#define @[get(F)@] @[(void)!fread(&((F).d),sizeof((F).d),1,(F).f)@] + +#define @[pascal_close(F)@] @[fclose((F).f)@] +#define @[eof(F)@] @[feof((F).f)@] +#define @[eoln(F)@] @[((F).d=='\n'||eof(F))@] +#define @[erstat(F)@] @[((F).f==NULL?-1:ferror((F).f))@] + +#define @[pascal_read(F,X)@] @[((X)=(F).d,get(F))@] +#define @[read_ln(F)@] do get(F); while (!eoln(F)) + +#define @[pascal_write(F, FMT,...)@] @[fprintf(F.f,FMT,## __VA_ARGS__)@] +#define @[write_ln(F,...)@] @[pascal_write(F,__VA_ARGS__"\n")@] + +#define @[wterm(FMT,...)@] @[pascal_write(term_out,FMT, ## __VA_ARGS__)@] +#define @[wterm_ln(FMT,...)@] @[wterm(FMT "\n", ## __VA_ARGS__)@] +#define wterm_cr @[pascal_write(term_out,"\n")@] +#define @[wlog(FMT, ...)@] @[pascal_write(log_file,FMT, ## __VA_ARGS__)@] +#define @[wlog_ln(FMT, ...)@] @[wlog(FMT "\n", ## __VA_ARGS__)@] +#define wlog_cr @[pascal_write(log_file,"\n")@] + +@ To end a line of text output, we call |print_ln|. + +@= +static void print_ln(void) /*prints an end-of-line*/ +{@+switch (selector) { +case term_and_log: {@+wterm_cr;wlog_cr; + term_offset=0;file_offset=0; + } @+break; +case log_only: {@+wlog_cr;file_offset=0; + } @+break; +case term_only: {@+wterm_cr;term_offset=0; + } @+break; +case no_print: case pseudo: case new_string: do_nothing;@+break; +default:write_ln(write_file[selector]); +} @/ +} /*|tally| is not affected*/ + +@ The |print_char| procedure sends one character to the desired destination, +using the |xchr| array to map it into an external character compatible with +|input_ln|. All printing comes through |print_ln| or |print_char|. + +@= +static void print_char(ASCII_code @!s) /*prints a single character*/ +{@+ +if (@) + if (selector < pseudo) + {@+print_ln();return; + } +switch (selector) { +case term_and_log: {@+wterm("%c",xchr[s]);wlog("%c",xchr[s]); + incr(term_offset);incr(file_offset); + if (term_offset==max_print_line) + {@+wterm_cr;term_offset=0; + } + if (file_offset==max_print_line) + {@+wlog_cr;file_offset=0; + } + } @+break; +case log_only: {@+wlog("%c",xchr[s]);incr(file_offset); + if (file_offset==max_print_line) print_ln(); + } @+break; +case term_only: {@+wterm("%c",xchr[s]);incr(term_offset); + if (term_offset==max_print_line) print_ln(); + } @+break; +case no_print: do_nothing;@+break; +case pseudo: if (tally < trick_count) trick_buf[tally%error_line]=s;@+break; +case new_string: {@+if (pool_ptr < pool_size) append_char(s); + } @+break; /*we drop characters if the string space is full*/ +default:pascal_write(write_file[selector],"%c", xchr[s]); +} @/ +incr(tally); +} + +@ An entire string is output by calling |print|. Note that if we are outputting +the single standard ASCII character \.c, we could call |print('c')|, since +|'c'==99| is the number of a single-character string, as explained above. But +|print_char('c')| is quicker, so \TeX\ goes directly to the |print_char| +routine when it knows that this is safe. (The present implementation +assumes that it is always safe to print a visible ASCII character.) +@^system dependencies@> + +@= +static void print(char *s) /* the simple version */ +{ @+if (s == NULL) s="???"; /*this can't happen*/ + while (*s!=0) print_char(*s++);@+ +} + +static void printn(int @!s) /*prints string |s|*/ +{@+ +pool_pointer j; /*current character code position*/ +int @!nl; /*new-line character to restore*/ +if (s >= str_ptr) {print("???"); return;}/*this can't happen*/ +@.???@> +else if (s < 256) + if (s < 0) { print("???");return; } /*can't happen*/ + else{@+if (selector > pseudo) + {@+print_char(s);return; /*internal strings are not expanded*/ + } + if ((@)) + if (selector < pseudo) + {@+print_ln();return; + } + nl=new_line_char;new_line_char=-1; + /*temporarily disable new-line character*/ + j=str_start[s]; + while (j < str_start[s+1]) + {@+print_char(so(str_pool[j]));incr(j); + } + new_line_char=nl;return; + } +j=str_start[s]; +while (j < str_start[s+1]) + {@+print_char(so(str_pool[j]));incr(j); + } +} + +@ Control sequence names, file names, and strings constructed with +\.{\\string} might contain |ASCII_code| values that can't +be printed using |print_char|. Therefore we use |slow_print| for them: + +@= +static void slow_print(int @!s) /*prints string |s|*/ +{@+pool_pointer j; /*current character code position*/ +if ((s >= str_ptr)||(s < 256)) printn(s); +else{@+j=str_start[s]; + while (j < str_start[s+1]) + {@+printn(so(str_pool[j]));incr(j); + } + } +} + +@ Here is the very first thing that \TeX\ prints: a headline that identifies +the version number and format package. The |term_offset| variable is temporarily +incorrect, but the discrepancy is not serious since we assume that this +part of the program is system dependent. +@^system dependencies@> + +According to the conventions of \TeX\ Live, + we print the |dump_name| if no format identifier is known. +@= +wterm("%s",banner); +if (format_ident==0) wterm_ln(" (preloaded format=%s)", dump_name); +else{@+slow_print(format_ident);print_ln(); + } +update_terminal; + +@ The procedure |print_nl| is like |print|, but it makes sure that the +string appears at the beginning of a new line. + +@= +static void print_nl(char *@!s) /*prints string |s| at beginning of line*/ +{@+if (((term_offset > 0)&&(odd(selector)))||@| + ((file_offset > 0)&&(selector >= log_only))) print_ln(); +print(s); +} + +@ The procedure |print_esc| prints a string that is preceded by +the user's escape character (which is usually a backslash). + +@= +static void printn_esc(str_number @!s) /*prints escape character, then |s|*/ +{@+int c; /*the escape character code*/ +@; +if (c >= 0) if (c < 256) printn(c); +slow_print(s); +} + +static void print_esc(char *@!s) /*the fast way*/ +{@+int c; /*the escape character code*/ +@; +if (c >= 0) if (c < 256) printn(c); +print(s); +} + +@ An array of digits in the range |0 dotdot 15| is printed by |print_the_digs|. + +@= +static void print_the_digs(eight_bits @!k) + /*prints |dig[k-1]|$\,\ldots\,$|dig[0]|*/ +{@+while (k > 0) + {@+decr(k); + if (dig[k] < 10) print_char('0'+dig[k]); + else print_char('A'-10+dig[k]); + } +} + +@ The following procedure, which prints out the decimal representation of a +given integer |n|, has been written carefully so that it works properly +if |n==0| or if |(-n)| would cause overflow. It does not apply |%| or |/| +to negative arguments, since such operations are not implemented consistently +by all \PASCAL\ compilers. + +@= +static void print_int(int @!n) /*prints an integer in decimal form*/ +{@+int k; /*index to current digit; we assume that $\vert n\vert<10^{23}$*/ +int @!m; /*used to negate |n| in possibly dangerous cases*/ +k=0; +if (n < 0) + {@+print_char('-'); + if (n > -100000000) negate(n); + else{@+m=-1-n;n=m/10;m=(m%10)+1;k=1; + if (m < 10) dig[0]=m; + else{@+dig[0]=0;incr(n); + } + } + } +@/do@+{dig[k]=n%10;n=n/10;incr(k); +}@+ while (!(n==0)); +print_the_digs(k); +} + +@ Here is a trivial procedure to print two digits; it is usually called with +a parameter in the range |0 <= n <= 99|. + +@p static void print_two(int @!n) /*prints two least significant digits*/ +{@+n=abs(n)%100;print_char('0'+(n/10)); +print_char('0'+(n%10)); +} + +@ Hexadecimal printing of nonnegative integers is accomplished by |print_hex|. + +@p static void print_hex(int @!n) + /*prints a positive integer in hexadecimal form*/ +{@+int k; /*index to current digit; we assume that $0\le n<16^{22}$*/ +k=0;print_char('"'); +@/do@+{dig[k]=n%16;n=n/16;incr(k); +}@+ while (!(n==0)); +print_the_digs(k); +} + +@ Old versions of \TeX\ needed a procedure called |print_ASCII| whose function +is now subsumed by |print|. We retain the old name here as a possible aid to +future software arch\ae ologists. + +@d print_ASCII printn + +@ Roman numerals are produced by the |print_roman_int| routine. Readers +who like puzzles might enjoy trying to figure out how this tricky code +works; therefore no explanation will be given. Notice that 1990 yields +\.{mcmxc}, not \.{mxm}. + +@p static void print_roman_int(int @!n) +{@+ +pool_pointer j, @!k; /*mysterious indices into |mystery|*/ +nonnegative_integer @!u, @!v; /*mysterious numbers*/ +const char mystery[] ="m2d5c2l5x2v5i"; +j=0;v=1000; +loop@+{@+while (n >= v) + {@+print_char(so(mystery[j]));n=n-v; + } + if (n <= 0) return; /*nonpositive input produces no output*/ + k=j+2;u=v/(so(mystery[k-1])-'0'); + if (mystery[k-1]==si('2')) + {@+k=k+2;u=u/(so(mystery[k-1])-'0'); + } + if (n+u >= v) + {@+print_char(so(mystery[k]));n=n+u; + } + else{@+j=j+2;v=v/(so(mystery[j-1])-'0'); + } + } +} + +@ The |print| subroutine will not print a string that is still being +created. The following procedure will. + +@p static void print_current_string(void) /*prints a yet-unmade string*/ +{@+pool_pointer j; /*points to current character code*/ +j=str_start[str_ptr]; +while (j < pool_ptr) + {@+print_char(so(str_pool[j]));incr(j); + } +} + +@ Here is a procedure that asks the user to type a line of input, +assuming that the |selector| setting is either |term_only| or |term_and_log|. +The input is placed into locations |first| through |last-1| of the +|buffer| array, and echoed on the transcript file if appropriate. + +This procedure is never called when |interaction < scroll_mode|. + +@d prompt_input(A) {@+wake_up_terminal;print(A);term_input(); + } /*prints a string and gets a line of input*/ + +@p static void term_input(void) /*gets a line from the terminal*/ +{@+int k; /*index into |buffer|*/ +update_terminal; /*now the user sees the prompt for sure*/ +if (!input_ln(&term_in, true)) fatal_error("End of file on the terminal!"); +@.End of file on the terminal@> +term_offset=0; /*the user's line ended with \<\rm return>*/ +decr(selector); /*prepare to echo the input*/ +if (last!=first) for (k=first; k<=last-1; k++) printn(buffer[k]); +print_ln();incr(selector); /*restore previous status*/ +} + +@* Reporting errors. +When something anomalous is detected, \TeX\ typically does something like this: +$$\vbox{\halign{#\hfil\cr +|print_err("Something anomalous has been detected");|\cr +|help3("This is the first line of my offer to help.")|\cr +|("This is the second line. I'm trying to")|\cr +|("explain the best way for you to proceed.");|\cr +|error;|\cr}}$$ +A two-line help message would be given using |help2|, etc.; these informal +helps should use simple vocabulary that complements the words used in the +official error message that was printed. (Outside the U.S.A., the help +messages should preferably be translated into the local vernacular. Each +line of help is at most 60 characters long, in the present implementation, +so that |max_print_line| will not be exceeded.) + +The |print_err| procedure supplies a `\.!' before the official message, +and makes sure that the terminal is awake if a stop is going to occur. +The |error| procedure supplies a `\..' after the official message, then it +shows the location of the error; and if |interaction==error_stop_mode|, +it also enters into a dialog with the user, during which time the help +message may be printed. +@^system dependencies@> + +@= +static void print_err(char *s) +{@+if (interaction==error_stop_mode) wake_up_terminal; + if (filelineerrorstylep) print_file_line(); /* \TeX\ Live */ + else print_nl("! "); + print(s); +} + +@ The global variable |interaction| has four settings, representing increasing +amounts of user interaction: + +@d batch_mode 0 /*omits all stops and omits terminal output*/ +@d nonstop_mode 1 /*omits all stops*/ +@d scroll_mode 2 /*omits error stops*/ +@d error_stop_mode 3 /*stops at every opportunity to interact*/ + +@= +static int @!interaction; /*current level of interaction*/ + +@ @= +if (interaction_option<0) interaction=error_stop_mode; +else interaction=interaction_option; /* \TeX\ Live */ + +@ \TeX\ is careful not to call |error| when the print |selector| setting +might be unusual. The only possible values of |selector| at the time of +error messages are + +\yskip\hang|no_print| (when |interaction==batch_mode| + and |log_file| not yet open); + +\hang|term_only| (when |interaction > batch_mode| and |log_file| not yet open); + +\hang|log_only| (when |interaction==batch_mode| and |log_file| is open); + +\hang|term_and_log| (when |interaction > batch_mode| and |log_file| is open). + +@= +if (interaction==batch_mode) selector=no_print;@+else selector=term_only + +@ A global variable |deletions_allowed| is set |false| if the |get_next| +routine is active when |error| is called; this ensures that |get_next| +and related routines like |get_token| will never be called recursively. +A similar interlock is provided by |set_box_allowed|. +@^recursion@> + +The global variable |history| records the worst level of error that +has been detected. It has four possible values: |spotless|, |warning_issued|, +|error_message_issued|, and |fatal_error_stop|. + +Another global variable, |error_count|, is increased by one when an +|error| occurs without an interactive dialog, and it is reset to zero at +the end of every paragraph. If |error_count| reaches 100, \TeX\ decides +that there is no point in continuing further. + +@d spotless 0 /*|history| value when nothing has been amiss yet*/ +@d warning_issued 1 /*|history| value when |begin_diagnostic| has been called*/ +@d error_message_issued 2 /*|history| value when |error| has been called*/ +@d fatal_error_stop 3 /*|history| value when termination was premature*/ + +@= +static bool @!deletions_allowed; /*is it safe for |error| to call |get_token|?*/ +static bool @!set_box_allowed; /*is it safe to do a \.{\\setbox} assignment?*/ +static int @!history; /*has the source input been clean so far?*/ +static int @!error_count; /*the number of scrolled errors since the + last paragraph ended*/ + +@ The value of |history| is initially |fatal_error_stop|, but it will +be changed to |spotless| if \TeX\ survives the initialization process. + +@= +deletions_allowed=true;set_box_allowed=true; +error_count=0; /*|history| is initialized elsewhere*/ + +@ Since errors can be detected almost anywhere in \TeX, we want to declare the +error procedures near the beginning of the program. But the error procedures +in turn use some other procedures, which need to be declared |forward| +before we get to |error| itself. + +It is possible for |error| to be called recursively if some error arises +when |get_token| is being used to delete a token, and/or if some fatal error +occurs while \TeX\ is trying to fix a non-fatal one. But such recursion +@^recursion@> +is never more than two levels deep. + +@= +static void normalize_selector(void);@/ +static void get_token(void);@/ +static void term_input(void);@/ +static void show_context(void);@/ +static void begin_file_reading(void);@/ +static void open_log_file(void);@/ +static void close_files_and_terminate(void);@/ +static void clear_for_error_prompt(void);@/ +static void give_err_help(void);@/ +#ifdef @!DEBUG +static void debug_help(void); +#else +#define debug_help() do_nothing +#endif + +@ Individual lines of help are recorded in the array |help_line|, which +contains entries in positions |0 dotdot(help_ptr-1)|. They should be printed +in reverse order, i.e., with |help_line[0]| appearing last. + +@d hlp1(A) help_line[0]=A;@+} +@d hlp2(A, B) help_line[1]=A;help_line[0]=B;@+} +@d hlp3(A, B, C) help_line[2]=A;help_line[1]=B;help_line[0]=C;@+} +@d hlp4(A, B, C, D) help_line[3]=A;help_line[2]=B;help_line[1]=C;help_line[0]=D;@+} +@d hlp5(A, B, C, D, E) help_line[4]=A;help_line[3]=B;help_line[2]=C;help_line[1]=D;help_line[0]=E;@+} +@d hlp6(A, B, C, D, E, F) help_line[5]=A;help_line[4]=B;help_line[3]=C;help_line[2]=D;help_line[1]=E;help_line[0]=F;@+} +@d help0 help_ptr=0 /*sometimes there might be no help*/ +@d help1(A) @+{@+help_ptr=1;hlp1(A) /*use this with one help line*/ +@d help2(A, B) @+{@+help_ptr=2;hlp2(A, B) /*use this with two help lines*/ +@d help3(A, B, C) @+{@+help_ptr=3;hlp3(A, B, C) /*use this with three help lines*/ +@d help4(A, B, C, D) @+{@+help_ptr=4;hlp4(A, B, C, D) /*use this with four help lines*/ +@d help5(A, B, C, D, E) @+{@+help_ptr=5;hlp5(A, B, C, D, E) /*use this with five help lines*/ +@d help6(A, B, C, D, E, F) @+{@+help_ptr=6;hlp6(A, B, C, D, E, F) /*use this with six help lines*/ + +@= +static char *@!help_line[6]; /*helps for the next |error|*/ +static int @!help_ptr; /*the number of help lines present*/ +static bool @!use_err_help; /*should the |err_help| list be shown?*/ + +@ @= +help_ptr=0;use_err_help=false; + +@ The |jump_out| procedure just cuts across all active procedure levels and +goes to |end_of_TEX|. This is the only nontrivial |@!goto| statement in the +whole program. It is used when there is no recovery from a particular error. + +Some \PASCAL\ compilers do not implement non-local |goto| statements. +@^system dependencies@> +In such cases the body of |jump_out| should simply be +`|close_files_and_terminate|;\thinspace' followed by a call on some system +procedure that quietly terminates the program. + +@= +static void jump_out(void) +{@+ close_files_and_terminate(); exit(0); +} + +@ Here now is the general |error| routine. + +@= +static void error(void) /*completes the job of error reporting*/ +{@+ +ASCII_code c; /*what the user types*/ +int @!s1, @!s2, @!s3, @!s4; + /*used to save global variables when deleting tokens*/ +if (history < error_message_issued) history=error_message_issued; +print_char('.');show_context(); +if (interaction==error_stop_mode) + @; +incr(error_count); +if (error_count==100) + {@+print_nl("(That makes 100 errors; please try again.)"); +@.That makes 100 errors...@> + history=fatal_error_stop;jump_out(); + } +@; +} + +@ @= +loop@+{@+resume: if (interaction!=error_stop_mode) return; + clear_for_error_prompt();prompt_input("? "); +@.?\relax@> + if (last==first) return; + c=buffer[first]; + if (c >= 'a') c=c+'A'-'a'; /*convert to uppercase*/ + @; + } + +@ It is desirable to provide an `\.E' option here that gives the user +an easy way to return from \TeX\ to the system editor, with the offending +line ready to be edited. But such an extension requires some system +wizardry, so the present implementation simply types out the name of the +file that should be +edited and the relevant line number. +@^system dependencies@> + +There is a secret `\.D' option available when the debugging routines haven't +been commented~out. +@^debugging@> + +@= +switch (c) { +case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': if (deletions_allowed) + @@;@+break; +@t\4\4@>@; +#ifdef @!DEBUG +case 'D': {@+debug_help();goto resume;@+} +#endif +case 'E': if (base_ptr > 0) if (input_stack[base_ptr].name_field >= 256) + {@+print_nl("You want to edit file "); +@.You want to edit file x@> + slow_print(input_stack[base_ptr].name_field); + print(" at line ");print_int(line); + interaction=scroll_mode;jump_out(); + } @+break; +case 'H': @@; +case 'I': @@; +case 'Q': case 'R': case 'S': @@; +case 'X': {@+interaction=scroll_mode;jump_out(); + } @+break; +default:do_nothing; +} @/ +@@; + +@ @= +{@+print("Type to proceed, S to scroll future error messages,");@/ +@.Type to proceed...@> +print_nl("R to run without stopping, Q to run quietly,");@/ +print_nl("I to insert something, "); +if (base_ptr > 0) if (input_stack[base_ptr].name_field >= 256) + print("E to edit your file,"); +if (deletions_allowed) + print_nl("1 or ... or 9 to ignore the next 1 to 9 tokens of input,"); +print_nl("H for help, X to quit."); +} + +@ Here the author of \TeX\ apologizes for making use of the numerical +relation between |'Q'|, |'R'|, |'S'|, and the desired interaction settings +|batch_mode|, |nonstop_mode|, |scroll_mode|. +@^Knuth, Donald Ervin@> + +@= +{@+error_count=0;interaction=batch_mode+c-'Q'; +print("OK, entering "); +switch (c) { +case 'Q': {@+print_esc("batchmode");decr(selector); + } @+break; +case 'R': print_esc("nonstopmode");@+break; +case 'S': print_esc("scrollmode"); +} /*there are no other cases*/ +print("...");print_ln();update_terminal;return; +} + +@ When the following code is executed, |buffer[(first+1)dotdot(last-1)]| may +contain the material inserted by the user; otherwise another prompt will +be given. In order to understand this part of the program fully, you need +to be familiar with \TeX's input stacks. + +@= +{@+begin_file_reading(); /*enter a new syntactic level for terminal input*/ + /*now |state==mid_line|, so an initial blank space will count as a blank*/ +if (last > first+1) + {@+loc=first+1;buffer[first]=' '; + } +else{@+prompt_input("insert>");loc=first; +@.insert>@> + } +first=last; +cur_input.limit_field=last-1; /*no |end_line_char| ends this line*/ +return; +} + +@ We allow deletion of up to 99 tokens at a time. + +@= +{@+s1=cur_tok;s2=cur_cmd;s3=cur_chr;s4=align_state; +align_state=1000000;OK_to_interrupt=false; +if ((last > first+1)&&(buffer[first+1] >= '0')&&(buffer[first+1] <= '9')) + c=c*10+buffer[first+1]-'0'*11; +else c=c-'0'; +while (c > 0) + {@+get_token(); /*one-level recursive call of |error| is possible*/ + decr(c); + } +cur_tok=s1;cur_cmd=s2;cur_chr=s3;align_state=s4;OK_to_interrupt=true; +help2("I have just deleted some text, as you asked.",@/ +"You can now delete more, or insert, or whatever."); +show_context();goto resume; +} + +@ @= +{@+if (use_err_help) + {@+give_err_help();use_err_help=false; + } +else{@+if (help_ptr==0) + help2("Sorry, I don't know how to help in this situation.",@/ + @t\kern1em@>"Maybe you should try asking a human?"); + @/do@+{decr(help_ptr);print(help_line[help_ptr]);print_ln(); + }@+ while (!(help_ptr==0)); + } +help4("Sorry, I already gave what help I could...",@/ + "Maybe you should try asking a human?",@/ + "An error might have occurred before I noticed any problems.",@/ + "``If all else fails, read the instructions.'");@/ +goto resume; +} + +@ @= +if (interaction > batch_mode) decr(selector); /*avoid terminal output*/ +if (use_err_help) + {@+print_ln();give_err_help(); + } +else while (help_ptr > 0) + {@+decr(help_ptr);print_nl(help_line[help_ptr]); + } +print_ln(); +if (interaction > batch_mode) incr(selector); /*re-enable terminal output*/ +print_ln() + +@ A dozen or so error messages end with a parenthesized integer, so we +save a teeny bit of program space by declaring the following procedure: + +@p static void int_error(int @!n) +{@+print(" (");print_int(n);print_char(')');error(); +} + +@ In anomalous cases, the print selector might be in an unknown state; +the following subroutine is called to fix things just enough to keep +running a bit longer. + +@p static void normalize_selector(void) +{@+if (log_opened) selector=term_and_log; +else selector=term_only; +if (job_name==0) open_log_file(); +if (interaction==batch_mode) decr(selector); +} + +@ The following procedure prints \TeX's last words before dying. + +@d succumb {@+if (interaction==error_stop_mode) + interaction=scroll_mode; /*no more interaction*/ + if (log_opened) error(); + if (interaction > batch_mode) debug_help(); + history=fatal_error_stop;jump_out(); /*irrecoverable error*/ + } + +@= +static void fatal_error(char *@!s) /*prints |s|, and that's it*/ +{@+normalize_selector();@/ +print_err("Emergency stop");help1(s);succumb; +@.Emergency stop@> +} + +@ Here is the most dreaded error message. + +@= +static void overflow(char *@!s, int @!n) /*stop due to finiteness*/ +{@+normalize_selector(); +print_err("TeX capacity exceeded, sorry ["); +@.TeX capacity exceeded ...@> +print(s);print_char('=');print_int(n);print_char(']'); +help2("If you really absolutely need more capacity,",@/ + "you can ask a wizard to enlarge me."); +succumb; +} + +@ The program might sometime run completely amok, at which point there is +no choice but to stop. If no previous error has been detected, that's bad +news; a message is printed that is really intended for the \TeX\ +maintenance person instead of the user (unless the user has been +particularly diabolical). The index entries for `this can't happen' may +help to pinpoint the problem. +@^dry rot@> + +@= +static void confusion(char *@!s) + /*consistency check violated; |s| tells where*/ +{@+normalize_selector(); +if (history < error_message_issued) + {@+print_err("This can't happen (");print(s);print_char(')'); +@.This can't happen@> + help1("I'm broken. Please show this to someone who can fix can fix"); + } +else{@+print_err("I can't go on meeting you like this"); +@.I can't go on...@> + help2("One of your faux pas seems to have wounded me deeply...",@/ + "in fact, I'm barely conscious. Please fix it and try again."); + } +succumb; +} + +@ Users occasionally want to interrupt \TeX\ while it's running. +If the \PASCAL\ runtime system allows this, one can implement +a routine that sets the global variable |interrupt| to some nonzero value +when such an interrupt is signalled. Otherwise there is probably at least +a way to make |interrupt| nonzero using the \PASCAL\ debugger. +@^system dependencies@> +@^debugging@> + +@d check_interrupt {@+if (interrupt!=0) pause_for_instructions(); + } + +@= +static int @!interrupt; /*should \TeX\ pause for instructions?*/ +static bool @!OK_to_interrupt; /*should interrupts be observed?*/ + +@ @= +interrupt=0;OK_to_interrupt=true; + +@ When an interrupt has been detected, the program goes into its +highest interaction level and lets the user have nearly the full flexibility of +the |error| routine. \TeX\ checks for interrupts only at times when it is +safe to do this. + +@p static void pause_for_instructions(void) +{@+if (OK_to_interrupt) + {@+interaction=error_stop_mode; + if ((selector==log_only)||(selector==no_print)) + incr(selector); + print_err("Interruption"); +@.Interruption@> + help3("You rang?",@/ + "Try to insert an instruction for me (e.g., `I\\showlists'),",@/ + "unless you just want to quit by typing `X'."); + deletions_allowed=false;error();deletions_allowed=true; + interrupt=0; + } +} + +@* Arithmetic with scaled dimensions. +The principal computations performed by \TeX\ are done entirely in terms of +integers less than $2^{31}$ in magnitude; and divisions are done only when both +dividend and divisor are nonnegative. Thus, the arithmetic specified in this +program can be carried out in exactly the same way on a wide variety of +computers, including some small ones. Why? Because the arithmetic +calculations need to be spelled out precisely in order to guarantee that +\TeX\ will produce identical output on different machines. If some +quantities were rounded differently in different implementations, we would +find that line breaks and even page breaks might occur in different places. +Hence the arithmetic of \TeX\ has been designed with care, and systems that +claim to be implementations of \TeX82 should follow precisely the +@:TeX82}{\TeX82@> +calculations as they appear in the present program. + +(Actually there are three places where \TeX\ uses |/| with a possibly negative +numerator. These are harmless; see |/| in the index. Also if the user +sets the \.{\\time} or the \.{\\year} to a negative value, some diagnostic +information will involve negative-numerator division. The same remarks +apply for |%| as well as for |/|.) + +@ Here is a routine that calculates half of an integer, using an +unambiguous convention with respect to signed odd numbers. + +@p static int half(int @!x) +{@+if (odd(x)) return(x+1)/2; +else return x/2; +} + +@ Fixed-point arithmetic is done on {\sl scaled integers\/} that are multiples +of $2^{-16}$. In other words, a binary point is assumed to be sixteen bit +positions from the right end of a binary computer word. + +@d unity 0200000 /*$2^{16}$, represents 1.00000*/ +@d two 0400000 /*$2^{17}$, represents 2.00000*/ + +@= +typedef int scaled; /*this type is used for scaled integers*/ +typedef int32_t nonnegative_integer; /*$0\le x<2^{31}$*/ +typedef int8_t small_number; /*this type is self-explanatory*/ + +@ The following function is used to create a scaled integer from a given decimal +fraction $(.d_0d_1\ldots d_{k-1})$, where |0 <= k <= 17|. The digit $d_i$ is +given in |dig[i]|, and the calculation produces a correctly rounded result. + +@p static scaled round_decimals(small_number @!k) + /*converts a decimal fraction*/ +{@+int a; /*the accumulator*/ +a=0; +while (k > 0) + {@+decr(k);a=(a+dig[k]*two)/10; + } +return(a+1)/2; +} + +@ Conversely, here is a procedure analogous to |print_int|. If the output +of this procedure is subsequently read by \TeX\ and converted by the +|round_decimals| routine above, it turns out that the original value will +be reproduced exactly; the ``simplest'' such decimal number is output, +but there is always at least one digit following the decimal point. + +The invariant relation in the \&{repeat} loop is that a sequence of +decimal digits yet to be printed will yield the original number if and only if +they form a fraction~$f$ in the range $s-\delta\le 10\cdot2^{16}f unity) s=s+0100000-50000; /*round the last digit*/ +print_char('0'+(s/unity));s=10*(s%unity);delta=delta*10; +}@+ while (!(s <= delta)); +} + +@ Physical sizes that a \TeX\ user specifies for portions of documents are +represented internally as scaled points. Thus, if we define an `sp' (scaled +@^sp@> +point) as a unit equal to $2^{-16}$ printer's points, every dimension +inside of \TeX\ is an integer number of sp. There are exactly +4,736,286.72 sp per inch. Users are not allowed to specify dimensions +larger than $2^{30}-1$ sp, which is a distance of about 18.892 feet (5.7583 +meters); two such quantities can be added without overflow on a 32-bit +computer. + +The present implementation of \TeX\ does not check for overflow when +@^overflow in arithmetic@> +dimensions are added or subtracted. This could be done by inserting a +few dozen tests of the form `\ignorespaces|if (x >= 010000000000)| +\\{report\_overflow}', but the chance of overflow is so remote that +such tests do not seem worthwhile. + +\TeX\ needs to do only a few arithmetic operations on scaled quantities, +other than addition and subtraction, and the following subroutines do most of +the work. A single computation might use several subroutine calls, and it is +desirable to avoid producing multiple error messages in case of arithmetic +overflow; so the routines set the global variable |arith_error| to |true| +instead of reporting errors directly to the user. Another global variable, +|rem|, holds the remainder after a division. + +@= +static bool @!arith_error; /*has arithmetic overflow occurred recently?*/ +static scaled @!rem; /*amount subtracted to get an exact division*/ + +@ The first arithmetical subroutine we need computes $nx+y$, where |x| +and~|y| are |scaled| and |n| is an integer. We will also use it to +multiply integers. + +@d nx_plus_y(A, B, C) mult_and_add(A, B, C, 07777777777) +@d mult_integers(A, B) mult_and_add(A, B, 0, 017777777777) + +@p static scaled mult_and_add(int @!n, scaled @!x, scaled @!y, scaled @!max_answer) +{@+if (n < 0) + {@+negate(x);negate(n); + } +if (n==0) return y; +else if (((x <= (max_answer-y)/n)&&(-x <= (max_answer+y)/n))) + return n*x+y; +else{@+arith_error=true;return 0; + } +} + +@ We also need to divide scaled dimensions by integers. + +@p static scaled x_over_n(scaled @!x, int @!n) +{@+bool negative; /*should |rem| be negated?*/ +scaled x_over_n; +negative=false; +if (n==0) + {@+arith_error=true;x_over_n=0;rem=x; + } +else{@+if (n < 0) + {@+negate(x);negate(n);negative=true; + } + if (x >= 0) + {@+x_over_n=x/n;rem=x%n; + } + else{@+x_over_n=-((-x)/n);rem=-((-x)%n); + } + } +if (negative) negate(rem); +return x_over_n;} + +@ Then comes the multiplication of a scaled number by a fraction |n/(double)d|, +where |n| and |d| are nonnegative integers | <= @t$2^{16}$@>| and |d| is +positive. It would be too dangerous to multiply by~|n| and then divide +by~|d|, in separate operations, since overflow might well occur; and it +would be too inaccurate to divide by |d| and then multiply by |n|. Hence +this subroutine simulates 1.5-precision arithmetic. + +@p static scaled xn_over_d(scaled @!x, int @!n, int @!d) +{@+bool positive; /*was |x >= 0|?*/ +nonnegative_integer @!t, @!u, @!v; /*intermediate quantities*/ +scaled xn_over_d; +if (x >= 0) positive=true; +else{@+negate(x);positive=false; + } +t=(x%0100000)*n; +u=(x/0100000)*n+(t/0100000); +v=(u%d)*0100000+(t%0100000); +if (u/d >= 0100000) arith_error=true; +else u=0100000*(u/d)+(v/d); +if (positive) + {@+xn_over_d=u;rem=v%d; + } +else{@+xn_over_d=-u;rem=-(v%d); + } +return xn_over_d;} + +@ The next subroutine is used to compute the ``badness'' of glue, when a +total~|t| is supposed to be made from amounts that sum to~|s|. According +to {\sl The \TeX book}, the badness of this situation is $100(t/s)^3$; +however, badness is simply a heuristic, so we need not squeeze out the +last drop of accuracy when computing it. All we really want is an +approximation that has similar properties. +@:TeXbook}{\sl The \TeX book@> + +The actual method used to compute the badness is easier to read from the +program than to describe in words. It produces an integer value that is a +reasonably close approximation to $100(t/s)^3$, and all implementations +of \TeX\ should use precisely this method. Any badness of $2^{13}$ or more is +treated as infinitely bad, and represented by 10000. + +It is not difficult to prove that $$\hbox{|badness(t+1, s) >= badness(t, s) + >= badness(t, s+1)|}.$$ The badness function defined here is capable of +computing at most 1095 distinct values, but that is plenty. + +@d inf_bad 10000 /*infinitely bad value*/ + +@p @@/ +static halfword badness(scaled @!t, scaled @!s) /*compute badness, given |t >= 0|*/ +{@+int r; /*approximation to $\alpha t/s$, where $\alpha^3\approx + 100\cdot2^{18}$*/ +if (t==0) return 0; +else if (s <= 0) return inf_bad; +else{@+if (t <= 7230584) r=(t*297)/s; /*$297^3=99.94\times2^{18}$*/ + else if (s >= 1663497) r=t/(s/297); + else r=t; + if (r > 1290) return inf_bad; /*$1290^3<2^{31}<1291^3$*/ + else return(r*r*r+0400000)/01000000; + } /*that was $r^3/2^{18}$, rounded to the nearest integer*/ +} + +@ When \TeX\ ``packages'' a list into a box, it needs to calculate the +proportionality ratio by which the glue inside the box should stretch +or shrink. This calculation does not affect \TeX's decision making, +so the precise details of rounding, etc., in the glue calculation are not +of critical importance for the consistency of results on different computers. + +We shall use the type |glue_ratio| for such proportionality ratios. +A glue ratio should take the same amount of memory as an +|int| (usually 32 bits) if it is to blend smoothly with \TeX's +other data structures. Thus |glue_ratio| should be equivalent to +|short_real| in some implementations of \PASCAL. Alternatively, +it is possible to deal with glue ratios using nothing but fixed-point +arithmetic; see {\sl TUGboat \bf3},1 (March 1982), 10--27. (But the +routines cited there must be modified to allow negative glue ratios.) +@^system dependencies@> + +@d set_glue_ratio_zero(A) A=0.0 /*store the representation of zero ratio*/ +@d set_glue_ratio_one(A) A=1.0 /*store the representation of unit ratio*/ +@d unfix(A) ((double)(A)) /*convert from |glue_ratio| to type |double|*/ +@d fix(A) ((glue_ratio)(A)) /*convert from |double| to type |glue_ratio|*/ +@d float_constant(A) ((double)(A)) /*convert |int| constant to |double|*/ + +@= +#if __SIZEOF_FLOAT__==4 +typedef float float32_t; +#else +#error @=float type must have size 4@> +#endif +typedef float @!glue_ratio; /*one-word representation of a glue expansion factor*/ + +@* Packed data. +In order to make efficient use of storage space, \TeX\ bases its major data +structures on a |memory_word|, which contains either a (signed) integer, +possibly scaled, or a (signed) |glue_ratio|, or a small number of +fields that are one half or one quarter of the size used for storing +integers. + +If |x| is a variable of type |memory_word|, it contains up to four +fields that can be referred to as follows: +$$\vbox{\halign{\hfil#&#\hfil&#\hfil\cr +|x|&.|i|&(an |int|)\cr +|x|&.|sc|\qquad&(a |scaled| integer)\cr +|x|&.|gr|&(a |glue_ratio|)\cr +|x.hh.lh|, |x.hh|&.|rh|&(two halfword fields)\cr +|x.hh.b0|, |x.hh.b1|, |x.hh|&.|rh|&(two quarterword fields, one halfword + field)\cr +|x.qqqq.b0|, |x.qqqq.b1|, |x.qqqq|&.|b2|, |x.qqqq.b3|\hskip-100pt + &\qquad\qquad\qquad(four quarterword fields)\cr}}$$ +This is somewhat cumbersome to write, and not very readable either, but +macros will be used to make the notation shorter and more transparent. +The \PASCAL\ code below gives a formal definition of |memory_word| and +its subsidiary types, using packed variant records. \TeX\ makes no +assumptions about the relative positions of the fields within a word. + +Since we are assuming 32-bit integers, a halfword must contain at least +16 bits, and a quarterword must contain at least 8 bits. +@^system dependencies@> +But it doesn't hurt to have more bits; for example, with enough 36-bit +words you might be able to have |mem_max| as large as 262142, which is +eight times as much memory as anybody had during the first four years of +\TeX's existence. + +N.B.: Valuable memory space will be dreadfully wasted unless \TeX\ is compiled +by a \PASCAL\ that packs all of the |memory_word| variants into +the space of a single integer. This means, for example, that |glue_ratio| +words should be |short_real| instead of |double| on some computers. Some +\PASCAL\ compilers will pack an integer whose subrange is `|0 dotdot 255|' into +an eight-bit field, but others insist on allocating space for an additional +sign bit; on such systems you can get 256 values into a quarterword only +if the subrange is `|-128 dotdot 127|'. + +The present implementation tries to accommodate as many variations as possible, +so it makes few assumptions. If integers having the subrange +`|min_quarterword dotdot max_quarterword|' can be packed into a quarterword, +and if integers having the subrange `|min_halfword dotdot max_halfword|' +can be packed into a halfword, everything should work satisfactorily. + +It is usually most efficient to have |min_quarterword==min_halfword==0|, +so one should try to achieve this unless it causes a severe problem. +The values defined here are recommended for most 32-bit computers. + +@d min_quarterword 0 /*smallest allowable value in a |quarterword|*/ +@d max_quarterword 65535 /*largest allowable value in a |quarterword|*/ +@d min_halfword 0 /*smallest allowable value in a |halfword|*/ +@d max_halfword 0x3FFFFFFF /*largest allowable value in a |halfword|*/ + +@ Here are the inequalities that the quarterword and halfword values +must satisfy (or rather, the inequalities that they mustn't satisfy): + +@= +#ifdef @!INIT +if ((mem_min!=mem_bot)||(mem_max!=mem_top)) bad=10; +#endif +@;@/ +if ((mem_min > mem_bot)||(mem_max < mem_top)) bad=10; +if ((min_quarterword > 0)||(max_quarterword < 127)) bad=11; +if ((min_halfword > 0)||(max_halfword < 32767)) bad=12; +if ((min_quarterword < min_halfword)||@| + (max_quarterword > max_halfword)) bad=13; +if ((mem_min < min_halfword)||(mem_max >= max_halfword)||@| + (mem_bot-mem_min > max_halfword+1)) bad=14; +if ((font_base < min_quarterword)||(font_max > max_quarterword)) bad=15; +if (font_max > font_base+256) bad=16; +if ((save_size > max_halfword)||(max_strings > max_halfword)) bad=17; +if (buf_size > max_halfword) bad=18; +if (max_quarterword-min_quarterword < 255) bad=19; + +@ The operation of adding or subtracting |min_quarterword| occurs quite +frequently in \TeX, so it is convenient to abbreviate this operation +by using the macros |qi| and |qo| for input and output to and from +quarterword format. + +The inner loop of \TeX\ will run faster with respect to compilers +that don't optimize expressions like `|x+0|' and `|x-0|', if these +macros are simplified in the obvious way when |min_quarterword==0|. +@^inner loop@>@^system dependencies@> + +@d qi(A) A+min_quarterword + /*to put an |eight_bits| item into a quarterword*/ +@d qo(A) A-min_quarterword + /*to take an |eight_bits| item out of a quarterword*/ +@d hi(A) A+min_halfword + /*to put a sixteen-bit item into a halfword*/ +@d ho(A) A-min_halfword + /*to take a sixteen-bit item from a halfword*/ + +@ The reader should study the following definitions closely: +@^system dependencies@> + +@d sc i /*|scaled| data is equivalent to |int|*/ + +@= +typedef uint16_t quarterword; /*1/4 of a word*/ +typedef int32_t halfword; /*1/2 of a word*/ +typedef int8_t two_choices; /*used when there are two variants in a record*/ +typedef int8_t four_choices; /*used when there are four variants in a record*/ +typedef uint64_t fullword; +typedef struct { @;@/ + halfword @!rh; + union { + halfword @!lh; + struct { quarterword @!b0;quarterword @!b1;} ; + };} two_halves; +typedef struct { @;@/ + quarterword @!b0; + quarterword @!b1; + quarterword @!b2; + quarterword @!b3; + } four_quarters; +typedef struct { @;@/ + union { + fullword @!w; + int @!i; + glue_ratio @!gr; + two_halves @!hh; + four_quarters @!qqqq; + };} memory_word; +typedef struct {@+FILE *f;@+memory_word@,d;@+} word_file; + +@ When debugging, we may want to print a |memory_word| without knowing +what type it is; so we print it in all modes. +@^dirty \PASCAL@>@^debugging@> + +@p +#ifdef @!DEBUG +static void print_word(memory_word @!w) + /*prints |w| in all ways*/ +{@+print_int(w.i);print_char(' ');@/ +print_scaled(w.sc);print_char(' ');@/ +print_scaled(round(unity*unfix(w.gr)));print_ln();@/ +@^real multiplication@> +print_int(w.hh.lh);print_char('=');print_int(w.hh.b0);print_char(':'); +print_int(w.hh.b1);print_char(';');print_int(w.hh.rh);print_char(' ');@/ +print_int(w.qqqq.b0);print_char(':');print_int(w.qqqq.b1);print_char(':'); +print_int(w.qqqq.b2);print_char(':');print_int(w.qqqq.b3); +} +#endif + +@* Dynamic memory allocation. +The \TeX\ system does nearly all of its own memory allocation, so that it +can readily be transported into environments that do not have automatic +facilities for strings, garbage collection, etc., and so that it can be in +control of what error messages the user receives. The dynamic storage +requirements of \TeX\ are handled by providing a large array |mem| in +which consecutive blocks of words are used as nodes by the \TeX\ routines. + +Pointer variables are indices into this array, or into another array +called |eqtb| that will be explained later. A pointer variable might +also be a special flag that lies outside the bounds of |mem|, so we +allow pointers to assume any |halfword| value. The minimum halfword +value represents a null pointer. \TeX\ does not assume that |mem[null]| exists. + +@s pointer int +@d pointer halfword /*a flag or a location in |mem| or |eqtb|*/ +@d null min_halfword /*the null pointer*/ + +@= +static pointer @!temp_ptr; /*a pointer variable for occasional emergency use*/ + +@ The |mem| array is divided into two regions that are allocated separately, +but the dividing line between these two regions is not fixed; they grow +together until finding their ``natural'' size in a particular job. +Locations less than or equal to |lo_mem_max| are used for storing +variable-length records consisting of two or more words each. This region +is maintained using an algorithm similar to the one described in exercise +2.5--19 of {\sl The Art of Computer Programming}. However, no size field +appears in the allocated nodes; the program is responsible for knowing the +relevant size when a node is freed. Locations greater than or equal to +|hi_mem_min| are used for storing one-word records; a conventional +\.{AVAIL} stack is used for allocation in this region. + +Locations of |mem| between |mem_bot| and |mem_top| may be dumped as part +of preloaded format files, by the \.{INITEX} preprocessor. +@.INITEX@> +Production versions of \TeX\ may extend the memory at both ends in order to +provide more space; locations between |mem_min| and |mem_bot| are always +used for variable-size nodes, and locations between |mem_top| and |mem_max| +are always used for single-word nodes. + +The key pointers that govern |mem| allocation have a prescribed order: +$$\advance\thickmuskip-2mu +\hbox{|null <= mem_min <= mem_bot < lo_mem_max < + hi_mem_min < mem_top <= mem_end <= mem_max|.}$$ + +Empirical tests show that the present implementation of \TeX\ tends to +spend about 9\pct! of its running time allocating nodes, and about 6\pct! +deallocating them after their use. + +@= +static memory_word @!mem0[mem_max-mem_min+1], + *const @!mem = @!mem0-mem_min; /*the big dynamic storage area*/ +static pointer @!lo_mem_max; /*the largest location of variable-size memory in use*/ +static pointer @!hi_mem_min; /*the smallest location of one-word memory in use*/ + +@ In order to study the memory requirements of particular applications, it +is possible to prepare a version of \TeX\ that keeps track of current and +maximum memory usage. When code between the delimiters | +#ifdef @!STAT +| $\ldots$ +|@t\#\&{endif}@>| is not ``commented out,'' \TeX\ will run a bit slower but it will +report these statistics when |tracing_stats| is sufficiently large. + +@= +static int @!var_used, @!dyn_used; /*how much memory is in use*/ +#ifdef @!STAT +#define incr_dyn_used @[incr(dyn_used)@] +#define decr_dyn_used @[decr(dyn_used)@] +#else +#define incr_dyn_used +#define decr_dyn_used +#endif + +@ Let's consider the one-word memory region first, since it's the +simplest. The pointer variable |mem_end| holds the highest-numbered location +of |mem| that has ever been used. The free locations of |mem| that +occur between |hi_mem_min| and |mem_end|, inclusive, are of type +|two_halves|, and we write |info(p)| and |link(p)| for the |lh| +and |rh| fields of |mem[p]| when it is of this type. The single-word +free locations form a linked list +$$|avail|,\;\hbox{|link(avail)|},\;\hbox{|link(link(avail))|},\;\ldots$$ +terminated by |null|. + +@d link(A) mem[A].hh.rh /*the |link| field of a memory word*/ +@d info(A) mem[A].hh.lh /*the |info| field of a memory word*/ + +@= +static pointer @!avail; /*head of the list of available one-word nodes*/ +static pointer @!mem_end; /*the last one-word node used in |mem|*/ + +@ If memory is exhausted, it might mean that the user has forgotten +a right brace. We will define some procedures later that try to help +pinpoint the trouble. + +@p @@/ +@@; + +@ The function |get_avail| returns a pointer to a new one-word node whose +|link| field is null. However, \TeX\ will halt if there is no more room left. +@^inner loop@> + +If the available-space list is empty, i.e., if |avail==null|, +we try first to increase |mem_end|. If that cannot be done, i.e., if +|mem_end==mem_max|, we try to decrease |hi_mem_min|. If that cannot be +done, i.e., if |hi_mem_min==lo_mem_max+1|, we have to quit. + +@p static pointer get_avail(void) /*single-word node allocation*/ +{@+pointer p; /*the new node being got*/ +p=avail; /*get top location in the |avail| stack*/ +if (p!=null) avail=link(avail); /*and pop it off*/ +else if (mem_end < mem_max) /*or go into virgin territory*/ + {@+incr(mem_end);p=mem_end; + } +else{@+decr(hi_mem_min);p=hi_mem_min; + if (hi_mem_min <= lo_mem_max) + {@+runaway(); /*if memory is exhausted, display possible runaway text*/ + overflow("main memory size", mem_max+1-mem_min); + /*quit; all one-word nodes are busy*/ +@:TeX capacity exceeded main memory size}{\quad main memory size@> + } + } +link(p)=null; /*provide an oft-desired initialization of the new node*/ +#ifdef @!STAT +incr(dyn_used); +#endif +@; /*maintain statistics*/ +return p; +} + +@ Conversely, a one-word node is recycled by calling |free_avail|. +This routine is part of \TeX's ``inner loop,'' so we want it to be fast. +@^inner loop@> + +@d free_avail(A) /*single-word node liberation*/ + {@+link(A)=avail;avail=A; + decr_dyn_used; + } + +@ There's also a |fast_get_avail| routine, which saves the procedure-call +overhead at the expense of extra programming. This routine is used in +the places that would otherwise account for the most calls of |get_avail|. +@^inner loop@> + +@d fast_get_avail(A) @t@>@;@/ + {@+A=avail; /*avoid |get_avail| if possible, to save time*/ + if (A==null) A=get_avail(); + else{@+avail=link(A);link(A)=null; + incr_dyn_used; + } + } + +@ The procedure |flush_list(p)| frees an entire linked list of +one-word nodes that starts at position |p|. +@^inner loop@> + +@p static void flush_list(pointer @!p) /*makes list of single-word nodes + available*/ +{@+pointer @!q, @!r; /*list traversers*/ +if (p!=null) + {@+r=p; + @/do@+{q=r;r=link(r); +#ifdef @!STAT +decr(dyn_used); +#endif + }@+ while (!(r==null)); /*now |q| is the last node on the list*/ + link(q)=avail;avail=p; + } +} + +@ The available-space list that keeps track of the variable-size portion +of |mem| is a nonempty, doubly-linked circular list of empty nodes, +pointed to by the roving pointer |rover|. + +Each empty node has size 2 or more; the first word contains the special +value |max_halfword| in its |link| field and the size in its |info| field; +the second word contains the two pointers for double linking. + +Each nonempty node also has size 2 or more. Its first word is of type +|two_halves|\kern-1pt, and its |link| field is never equal to |max_halfword|. +Otherwise there is complete flexibility with respect to the contents +of its other fields and its other words. + +(We require |mem_max < max_halfword| because terrible things can happen +when |max_halfword| appears in the |link| field of a nonempty node.) + +@d empty_flag max_halfword /*the |link| of an empty variable-size node*/ +@d is_empty(A) (link(A)==empty_flag) /*tests for empty node*/ +@d node_size(A) info(A) /*the size field in empty variable-size nodes*/ +@d llink(A) info(A+1) /*left link in doubly-linked list of empty nodes*/ +@d rlink(A) link(A+1) /*right link in doubly-linked list of empty nodes*/ + +@= +static pointer @!rover; /*points to some node in the list of empties*/ + +@ A call to |get_node| with argument |s| returns a pointer to a new node +of size~|s|, which must be 2~or more. The |link| field of the first word +of this new node is set to null. An overflow stop occurs if no suitable +space exists. + +If |get_node| is called with $s=2^{30}$, it simply merges adjacent free +areas and returns the value |max_halfword|. + +@p static pointer get_node(int @!s) /*variable-size node allocation*/ +{@+ +pointer p; /*the node currently under inspection*/ +pointer @!q; /*the node physically after node |p|*/ +int @!r; /*the newly allocated node, or a candidate for this honor*/ +int @!t; /*temporary register*/ +restart: p=rover; /*start at some free node in the ring*/ +@/do@+{@; +@^inner loop@> +p=rlink(p); /*move to the next node in the ring*/ +}@+ while (!(p==rover)); /*repeat until the whole list has been traversed*/ +if (s==010000000000) + {@+return max_halfword; + } +if (lo_mem_max+2 < hi_mem_min) if (lo_mem_max+2 <= mem_bot+max_halfword) + @; +overflow("main memory size", mem_max+1-mem_min); + /*sorry, nothing satisfactory is left*/ +@:TeX capacity exceeded main memory size}{\quad main memory size@> +found: link(r)=null; /*this node is now nonempty*/ +#ifdef @!STAT +var_used=var_used+s; /*maintain usage statistics*/ +#endif +@;@/ +return r; +} + +@ The lower part of |mem| grows by 1000 words at a time, unless +we are very close to going under. When it grows, we simply link +a new node into the available-space list. This method of controlled +growth helps to keep the |mem| usage consecutive when \TeX\ is +implemented on ``virtual memory'' systems. +@^virtual memory@> + +@= +{@+if (hi_mem_min-lo_mem_max >= 1998) t=lo_mem_max+1000; +else t=lo_mem_max+1+(hi_mem_min-lo_mem_max)/2; + /*|lo_mem_max+2 <= t < hi_mem_min|*/ +p=llink(rover);q=lo_mem_max;rlink(p)=q;llink(rover)=q;@/ +if (t > mem_bot+max_halfword) t=mem_bot+max_halfword; +rlink(q)=rover;llink(q)=p;link(q)=empty_flag;node_size(q)=t-lo_mem_max;@/ +lo_mem_max=t;link(lo_mem_max)=null;info(lo_mem_max)=null; +rover=q;goto restart; +} + +@ Empirical tests show that the routine in this section performs a +node-merging operation about 0.75 times per allocation, on the average, +after which it finds that |r > p+1| about 95\pct! of the time. + +@= +q=p+node_size(p); /*find the physical successor*/ +@^inner loop@> +while (is_empty(q)) /*merge node |p| with node |q|*/ + {@+t=rlink(q); + if (q==rover) rover=t; + llink(t)=llink(q);rlink(llink(q))=t;@/ + q=q+node_size(q); + } +r=q-s; +if (r > p+1) @; +if (r==p) if (rlink(p)!=p) + @; +node_size(p)=q-p /*reset the size in case it grew*/ + +@ @= +{@+node_size(p)=r-p; /*store the remaining size*/ +@^inner loop@> +rover=p; /*start searching here next time*/ +goto found; +} + +@ Here we delete node |p| from the ring, and let |rover| rove around. + +@= +{@+rover=rlink(p);t=llink(p); +llink(rover)=t;rlink(t)=rover; +goto found; +} + +@ Conversely, when some variable-size node |p| of size |s| is no longer needed, +the operation |free_node(p, s)| will make its words available, by inserting +|p| as a new empty node just before where |rover| now points. +@^inner loop@> + +@p static void free_node(pointer @!p, halfword @!s) /*variable-size node + liberation*/ +{@+pointer q; /*|llink(rover)|*/ +node_size(p)=s;link(p)=empty_flag; +q=llink(rover);llink(p)=q;rlink(p)=rover; /*set both links*/ +llink(rover)=p;rlink(q)=p; /*insert |p| into the ring*/ +#ifdef @!STAT +var_used=var_used-s; +#endif +@; /*maintain statistics*/ +} + +@ Just before \.{INITEX} writes out the memory, it sorts the doubly linked +available space list. The list is probably very short at such times, so a +simple insertion sort is used. The smallest available location will be +pointed to by |rover|, the next-smallest by |rlink(rover)|, etc. + +@p +#ifdef @!INIT +static void sort_avail(void) /*sorts the available variable-size nodes + by location*/ +{@+pointer p, @!q, @!r; /*indices into |mem|*/ +pointer @!old_rover; /*initial |rover| setting*/ +p=get_node(010000000000); /*merge adjacent free areas*/ +p=rlink(rover);rlink(rover)=max_halfword;old_rover=rover; +while (p!=old_rover) @; +p=rover; +while (rlink(p)!=max_halfword) + {@+llink(rlink(p))=p;p=rlink(p); + } +rlink(p)=rover;llink(rover)=p; +} +#endif + +@ The following |while | loop is guaranteed to +terminate, since the list that starts at +|rover| ends with |max_halfword| during the sorting procedure. + +@= +if (p < rover) + {@+q=p;p=rlink(q);rlink(q)=rover;rover=q; + } +else{@+q=rover; + while (rlink(q) < p) q=rlink(q); + r=rlink(p);rlink(p)=rlink(q);rlink(q)=p;p=r; + } + +@* Data structures for boxes and their friends. +From the computer's standpoint, \TeX's chief mission is to create +horizontal and vertical lists. We shall now investigate how the elements +of these lists are represented internally as nodes in the dynamic memory. + +A horizontal or vertical list is linked together by |link| fields in +the first word of each node. Individual nodes represent boxes, glue, +penalties, or special things like discretionary hyphens; because of this +variety, some nodes are longer than others, and we must distinguish different +kinds of nodes. We do this by putting a `|type|' field in the first word, +together with the link and an optional `|subtype|'. + +@d type(A) mem[A].hh.b0 /*identifies what kind of node this is*/ +@d subtype(A) mem[A].hh.b1 /*secondary identification in some cases*/ + +@ A |@!char_node|, which represents a single character, is the most important +kind of node because it accounts for the vast majority of all boxes. +Special precautions are therefore taken to ensure that a |char_node| does +not take up much memory space. Every such node is one word long, and in fact +it is identifiable by this property, since other kinds of nodes have at least +two words, and they appear in |mem| locations less than |hi_mem_min|. +This makes it possible to omit the |type| field in a |char_node|, leaving +us room for two bytes that identify a |font| and a |character| within +that font. + +Note that the format of a |char_node| allows for up to 256 different +fonts and up to 256 characters per font; but most implementations will +probably limit the total number of fonts to fewer than 75 per job, +and most fonts will stick to characters whose codes are +less than 128 (since higher codes +are more difficult to access on most keyboards). + +Extensions of \TeX\ intended for oriental languages will need even more +than $256\times256$ possible characters, when we consider different sizes +@^oriental characters@>@^Chinese characters@>@^Japanese characters@> +and styles of type. It is suggested that Chinese and Japanese fonts be +handled by representing such characters in two consecutive |char_node| +entries: The first of these has |font==font_base|, and its |link| points +to the second; +the second identifies the font and the character dimensions. +The saving feature about oriental characters is that most of them have +the same box dimensions. The |character| field of the first |char_node| +is a ``\\{charext}'' that distinguishes between graphic symbols whose +dimensions are identical for typesetting purposes. (See the \MF\ manual.) +Such an extension of \TeX\ would not be difficult; further details are +left to the reader. + +In order to make sure that the |character| code fits in a quarterword, +\TeX\ adds the quantity |min_quarterword| to the actual code. + +Character nodes appear only in horizontal lists, never in vertical lists. + +@d is_char_node(A) (A >= hi_mem_min) + /*does the argument point to a |char_node|?*/ +@d font(A) type(A) /*the font code in a |char_node|*/ +@d character(A) subtype(A) /*the character code in a |char_node|*/ + +@ An |hlist_node| stands for a box that was made from a horizontal list. +Each |hlist_node| is seven words long, and contains the following fields +(in addition to the mandatory |type| and |link|, which we shall not +mention explicitly when discussing the other node types): The |height| and +|width| and |depth| are scaled integers denoting the dimensions of the +box. There is also a |shift_amount| field, a scaled integer indicating +how much this box should be lowered (if it appears in a horizontal list), +or how much it should be moved to the right (if it appears in a vertical +list). There is a |list_ptr| field, which points to the beginning of the +list from which this box was fabricated; if |list_ptr| is |null|, the box +is empty. Finally, there are three fields that represent the setting of +the glue: |glue_set(p)| is a word of type |glue_ratio| that represents +the proportionality constant for glue setting; |glue_sign(p)| is +|stretching| or |shrinking| or |normal| depending on whether or not the +glue should stretch or shrink or remain rigid; and |glue_order(p)| +specifies the order of infinity to which glue setting applies (|normal|, +|fil|, |fill|, or |filll|). The |subtype| field is not used. + +@d hlist_node 0 /*|type| of hlist nodes*/ +@d box_node_size 7 /*number of words to allocate for a box node*/ +@d width_offset 1 /*position of |width| field in a box node*/ +@d depth_offset 2 /*position of |depth| field in a box node*/ +@d height_offset 3 /*position of |height| field in a box node*/ +@d width(A) mem[A+width_offset].sc /*width of the box, in sp*/ +@d depth(A) mem[A+depth_offset].sc /*depth of the box, in sp*/ +@d height(A) mem[A+height_offset].sc /*height of the box, in sp*/ +@d shift_amount(A) mem[A+4].sc /*repositioning distance, in sp*/ +@d list_offset 5 /*position of |list_ptr| field in a box node*/ +@d list_ptr(A) link(A+list_offset) /*beginning of the list inside the box*/ +@d glue_order(A) subtype(A+list_offset) /*applicable order of infinity*/ +@d glue_sign(A) type(A+list_offset) /*stretching or shrinking*/ +@d normal 0 /*the most common case when several cases are named*/ +@d stretching 1 /*glue setting applies to the stretch components*/ +@d shrinking 2 /*glue setting applies to the shrink components*/ +@d glue_offset 6 /*position of |glue_set| in a box node*/ +@d glue_set(A) mem[A+glue_offset].gr + /*a word of type |glue_ratio| for glue setting*/ + +@ The |new_null_box| function returns a pointer to an |hlist_node| in +which all subfields have the values corresponding to `\.{\\hbox\{\}}'. +(The |subtype| field is set to |min_quarterword|, for historic reasons +that are no longer relevant.) + +@p static pointer new_null_box(void) /*creates a new box node*/ +{@+pointer p; /*the new node*/ +p=get_node(box_node_size);type(p)=hlist_node; +subtype(p)=min_quarterword; +width(p)=0;depth(p)=0;height(p)=0;shift_amount(p)=0;list_ptr(p)=null; +glue_sign(p)=normal;glue_order(p)=normal;set_glue_ratio_zero(glue_set(p)); +return p; +} + +@ A |vlist_node| is like an |hlist_node| in all respects except that it +contains a vertical list. + +@d vlist_node 1 /*|type| of vlist nodes*/ + +@ A |rule_node| stands for a solid black rectangle; it has |width|, +|depth|, and |height| fields just as in an |hlist_node|. However, if +any of these dimensions is $-2^{30}$, the actual value will be determined +by running the rule up to the boundary of the innermost enclosing box. +This is called a ``running dimension.'' The |width| is never running in +an hlist; the |height| and |depth| are never running in a~vlist. + +@d rule_node 2 /*|type| of rule nodes*/ +@d rule_node_size 4 /*number of words to allocate for a rule node*/ +@d null_flag -010000000000 /*$-2^{30}$, signifies a missing item*/ +@d is_running(A) (A==null_flag) /*tests for a running dimension*/ + +@ A new rule node is delivered by the |new_rule| function. It +makes all the dimensions ``running,'' so you have to change the +ones that are not allowed to run. + +@p static pointer new_rule(void) +{@+pointer p; /*the new node*/ +p=get_node(rule_node_size);type(p)=rule_node; +subtype(p)=0; /*the |subtype| is not used*/ +width(p)=null_flag;depth(p)=null_flag;height(p)=null_flag; +return p; +} + +@ Insertions are represented by |ins_node| records, where the |subtype| +indicates the corresponding box number. For example, `\.{\\insert 250}' +leads to an |ins_node| whose |subtype| is |250+min_quarterword|. +The |height| field of an |ins_node| is slightly misnamed; it actually holds +the natural height plus depth of the vertical list being inserted. +The |depth| field holds the |split_max_depth| to be used in case this +insertion is split, and the |split_top_ptr| points to the corresponding +|split_top_skip|. The |float_cost| field holds the |floating_penalty| that +will be used if this insertion floats to a subsequent page after a +split insertion of the same class. There is one more field, the +|ins_ptr|, which points to the beginning of the vlist for the insertion. + +@d ins_node 3 /*|type| of insertion nodes*/ +@d ins_node_size 5 /*number of words to allocate for an insertion*/ +@d float_cost(A) mem[A+1].i /*the |floating_penalty| to be used*/ +@d ins_ptr(A) info(A+4) /*the vertical list to be inserted*/ +@d split_top_ptr(A) link(A+4) /*the |split_top_skip| to be used*/ + +@ A |mark_node| has a |mark_ptr| field that points to the reference count +of a token list that contains the user's \.{\\mark} text. +In addition there is a |mark_class| field that contains the mark class. + +@d mark_node 4 /*|type| of a mark node*/ +@d small_node_size 2 /*number of words to allocate for most node types*/ +@d mark_ptr(A) link(A+1) /*head of the token list for a mark*/ +@d mark_class(A) info(A+1) /*the mark class*/ + +@ An |adjust_node|, which occurs only in horizontal lists, +specifies material that will be moved out into the surrounding +vertical list; i.e., it is used to implement \TeX's `\.{\\vadjust}' +operation. The |adjust_ptr| field points to the vlist containing this +material. + +@d adjust_node 5 /*|type| of an adjust node*/ +@d adjust_ptr(A) mem[A+1].i + /*vertical list to be moved out of horizontal list*/ + +@ A |ligature_node|, which occurs only in horizontal lists, specifies +a character that was fabricated from the interaction of two or more +actual characters. The second word of the node, which is called the +|lig_char| word, contains |font| and |character| fields just as in a +|char_node|. The characters that generated the ligature have not been +forgotten, since they are needed for diagnostic messages and for +hyphenation; the |lig_ptr| field points to a linked list of character +nodes for all original characters that have been deleted. (This list +might be empty if the characters that generated the ligature were +retained in other nodes.) + +The |subtype| field is 0, plus 2 and/or 1 if the original source of the +ligature included implicit left and/or right boundaries. + +@d ligature_node 6 /*|type| of a ligature node*/ +@d lig_char(A) A+1 /*the word where the ligature is to be found*/ +@d lig_ptr(A) link(lig_char(A)) /*the list of characters*/ + +@ The |new_ligature| function creates a ligature node having given +contents of the |font|, |character|, and |lig_ptr| fields. We also have +a |new_lig_item| function, which returns a two-word node having a given +|character| field. Such nodes are used for temporary processing as ligatures +are being created. + +@p static pointer new_ligature(quarterword @!f, quarterword @!c, pointer @!q) +{@+pointer p; /*the new node*/ +p=get_node(small_node_size);type(p)=ligature_node; +font(lig_char(p))=f;character(lig_char(p))=c;lig_ptr(p)=q; +subtype(p)=0;return p; +} +@# +static pointer new_lig_item(quarterword @!c) +{@+pointer p; /*the new node*/ +p=get_node(small_node_size);character(p)=c;lig_ptr(p)=null; +return p; +} + +@ A |disc_node|, which occurs only in horizontal lists, specifies a +``dis\-cretion\-ary'' line break. If such a break occurs at node |p|, the text +that starts at |pre_break(p)| will precede the break, the text that starts at +|post_break(p)| will follow the break, and text that appears in the next +|replace_count(p)| nodes will be ignored. For example, an ordinary +discretionary hyphen, indicated by `\.{\\-}', yields a |disc_node| with +|pre_break| pointing to a |char_node| containing a hyphen, |post_break==null|, +and |replace_count==0|. All three of the discretionary texts must be +lists that consist entirely of character, kern, box, rule, and ligature nodes. + +If |pre_break(p)==null|, the |ex_hyphen_penalty| will be charged for this +break. Otherwise the |hyphen_penalty| will be charged. The texts will +actually be substituted into the list by the line-breaking algorithm if it +decides to make the break, and the discretionary node will disappear at +that time; thus, the output routine sees only discretionaries that were +not chosen. + +@d disc_node 7 /*|type| of a discretionary node*/ +@d replace_count(A) subtype(A) /*how many subsequent nodes to replace*/ +@d pre_break(A) llink(A) /*text that precedes a discretionary break*/ +@d post_break(A) rlink(A) /*text that follows a discretionary break*/ + +@p static pointer new_disc(void) /*creates an empty |disc_node|*/ +{@+pointer p; /*the new node*/ +p=get_node(small_node_size);type(p)=disc_node; +replace_count(p)=0;pre_break(p)=null;post_break(p)=null; +return p; +} + +@ A |whatsit_node| is a wild card reserved for extensions to \TeX. The +|subtype| field in its first word says what `\\{whatsit}' it is, and +implicitly determines the node size (which must be 2 or more) and the +format of the remaining words. When a |whatsit_node| is encountered +in a list, special actions are invoked; knowledgeable people who are +careful not to mess up the rest of \TeX\ are able to make \TeX\ do new +things by adding code at the end of the program. For example, there +might be a `\TeX nicolor' extension to specify different colors of ink, +@^extensions to \TeX@> +and the whatsit node might contain the desired parameters. + +The present implementation of \TeX\ treats the features associated with +`\.{\\write}' and `\.{\\special}' as if they were extensions, in order to +illustrate how such routines might be coded. We shall defer further +discussion of extensions until the end of this program. + +@d whatsit_node 8 /*|type| of special extension nodes*/ + +@ A |math_node|, which occurs only in horizontal lists, appears before and +after mathematical formulas. The |subtype| field is |before| before the +formula and |after| after it. There is a |width| field, which represents +the amount of surrounding space inserted by \.{\\mathsurround}. + +@d math_node 9 /*|type| of a math node*/ +@d before 0 /*|subtype| for math node that introduces a formula*/ +@d after 1 /*|subtype| for math node that winds up a formula*/ + +@p static pointer new_math(scaled @!w, small_number @!s) +{@+pointer p; /*the new node*/ +p=get_node(small_node_size);type(p)=math_node; +subtype(p)=s;width(p)=w;return p; +} + +@ \TeX\ makes use of the fact that |hlist_node|, |vlist_node|, +|rule_node|, |ins_node|, |mark_node|, |adjust_node|, |ligature_node|, +|disc_node|, |whatsit_node|, and |math_node| are at the low end of the +type codes, by permitting a break at glue in a list if and only if the +|type| of the previous node is less than |math_node|. Furthermore, a +node is discarded after a break if its type is |math_node| or~more. + +@d precedes_break(A) (type(A) < math_node) +@d non_discardable(A) (type(A) < math_node) + +@ A |glue_node| represents glue in a list. However, it is really only +a pointer to a separate glue specification, since \TeX\ makes use of the +fact that many essentially identical nodes of glue are usually present. +If |p| points to a |glue_node|, |glue_ptr(p)| points to +another packet of words that specify the stretch and shrink components, etc. + +Glue nodes also serve to represent leaders; the |subtype| is used to +distinguish between ordinary glue (which is called |normal|) and the three +kinds of leaders (which are called |a_leaders|, |c_leaders|, and |x_leaders|). +The |leader_ptr| field points to a rule node or to a box node containing the +leaders; it is set to |null| in ordinary glue nodes. + +Many kinds of glue are computed from \TeX's ``skip'' parameters, and +it is helpful to know which parameter has led to a particular glue node. +Therefore the |subtype| is set to indicate the source of glue, whenever +it originated as a parameter. We will be defining symbolic names for the +parameter numbers later (e.g., |line_skip_code==0|, |baseline_skip_code==1|, +etc.); it suffices for now to say that the |subtype| of parametric glue +will be the same as the parameter number, plus~one. + +In math formulas there are two more possibilities for the |subtype| in a +glue node: |mu_glue| denotes an \.{\\mskip} (where the units are scaled \.{mu} +instead of scaled \.{pt}); and |cond_math_glue| denotes the `\.{\\nonscript}' +feature that cancels the glue node immediately following if it appears +in a subscript. + +@d glue_node 10 /*|type| of node that points to a glue specification*/ +@d cond_math_glue 98 /*special |subtype| to suppress glue in the next node*/ +@d mu_glue 99 /*|subtype| for math glue*/ +@d a_leaders 100 /*|subtype| for aligned leaders*/ +@d c_leaders 101 /*|subtype| for centered leaders*/ +@d x_leaders 102 /*|subtype| for expanded leaders*/ +@d glue_ptr(A) llink(A) /*pointer to a glue specification*/ +@d leader_ptr(A) rlink(A) /*pointer to box or rule node for leaders*/ + +@ A glue specification has a halfword reference count in its first word, +@^reference counts@> +representing |null| plus the number of glue nodes that point to it (less one). +Note that the reference count appears in the same position as +the |link| field in list nodes; this is the field that is initialized +to |null| when a node is allocated, and it is also the field that is flagged +by |empty_flag| in empty nodes. + +Glue specifications also contain three |scaled| fields, for the |width|, +|stretch|, and |shrink| dimensions. Finally, there are two one-byte +fields called |stretch_order| and |shrink_order|; these contain the +orders of infinity (|normal|, |fil|, |fill|, or |filll|) +corresponding to the stretch and shrink values. + +@d glue_spec_size 4 /*number of words to allocate for a glue specification*/ +@d glue_ref_count(A) link(A) /*reference count of a glue specification*/ +@d stretch(A) mem[A+2].sc /*the stretchability of this glob of glue*/ +@d shrink(A) mem[A+3].sc /*the shrinkability of this glob of glue*/ +@d stretch_order(A) type(A) /*order of infinity for stretching*/ +@d shrink_order(A) subtype(A) /*order of infinity for shrinking*/ +@d fil 1 /*first-order infinity*/ +@d fill 2 /*second-order infinity*/ +@d filll 3 /*third-order infinity*/ + +@= +typedef int8_t glue_ord; /*infinity to the 0, 1, 2, or 3 power*/ + +@ Here is a function that returns a pointer to a copy of a glue spec. +The reference count in the copy is |null|, because there is assumed +to be exactly one reference to the new specification. + +@p static pointer new_spec(pointer @!p) /*duplicates a glue specification*/ +{@+pointer q; /*the new spec*/ +q=get_node(glue_spec_size);@/ +mem[q]=mem[p];glue_ref_count(q)=null;@/ +width(q)=width(p);stretch(q)=stretch(p);shrink(q)=shrink(p); +return q; +} + +@ And here's a function that creates a glue node for a given parameter +identified by its code number; for example, +|new_param_glue(line_skip_code)| returns a pointer to a glue node for the +current \.{\\lineskip}. + +@p static pointer new_param_glue(small_number @!n) +{@+pointer p; /*the new node*/ +pointer @!q; /*the glue specification*/ +p=get_node(small_node_size);type(p)=glue_node;subtype(p)=n+1; +leader_ptr(p)=null;@/ +q=@@t@>; +glue_ptr(p)=q;incr(glue_ref_count(q)); +return p; +} + +@ Glue nodes that are more or less anonymous are created by |new_glue|, +whose argument points to a glue specification. + +@p static pointer new_glue(pointer @!q) +{@+pointer p; /*the new node*/ +p=get_node(small_node_size);type(p)=glue_node;subtype(p)=normal; +leader_ptr(p)=null;glue_ptr(p)=q;incr(glue_ref_count(q)); +return p; +} + +@ Still another subroutine is needed: This one is sort of a combination +of |new_param_glue| and |new_glue|. It creates a glue node for one of +the current glue parameters, but it makes a fresh copy of the glue +specification, since that specification will probably be subject to change, +while the parameter will stay put. The global variable |temp_ptr| is +set to the address of the new spec. + +@p static pointer new_skip_param(small_number @!n) +{@+pointer p; /*the new node*/ +temp_ptr=new_spec(@); +p=new_glue(temp_ptr);glue_ref_count(temp_ptr)=null;subtype(p)=n+1; +return p; +} + +@ A |kern_node| has a |width| field to specify a (normally negative) +amount of spacing. This spacing correction appears in horizontal lists +between letters like A and V when the font designer said that it looks +better to move them closer together or further apart. A kern node can +also appear in a vertical list, when its `|width|' denotes additional +spacing in the vertical direction. The |subtype| is either |normal| (for +kerns inserted from font information or math mode calculations) or |explicit| +(for kerns inserted from \.{\\kern} and \.{\\/} commands) or |acc_kern| +(for kerns inserted from non-math accents) or |mu_glue| (for kerns +inserted from \.{\\mkern} specifications in math formulas). + +@d kern_node 11 /*|type| of a kern node*/ +@d explicit 1 /*|subtype| of kern nodes from \.{\\kern} and \.{\\/}*/ +@d acc_kern 2 /*|subtype| of kern nodes from accents*/ + +@ The |new_kern| function creates a kern node having a given width. + +@p static pointer new_kern(scaled @!w) +{@+pointer p; /*the new node*/ +p=get_node(small_node_size);type(p)=kern_node; +subtype(p)=normal; +width(p)=w; +return p; +} + +@ A |penalty_node| specifies the penalty associated with line or page +breaking, in its |penalty| field. This field is a fullword integer, but +the full range of integer values is not used: Any penalty | >= 10000| is +treated as infinity, and no break will be allowed for such high values. +Similarly, any penalty | <= -10000| is treated as negative infinity, and a +break will be forced. + +@d penalty_node 12 /*|type| of a penalty node*/ +@d inf_penalty inf_bad /*``infinite'' penalty value*/ +@d eject_penalty (-inf_penalty) /*``negatively infinite'' penalty value*/ +@d penalty(A) mem[A+1].i /*the added cost of breaking a list here*/ + +@ Anyone who has been reading the last few sections of the program will +be able to guess what comes next. + +@p static pointer new_penalty(int @!m) +{@+pointer p; /*the new node*/ +p=get_node(small_node_size);type(p)=penalty_node; +subtype(p)=0; /*the |subtype| is not used*/ +penalty(p)=m;return p; +} + +@ You might think that we have introduced enough node types by now. Well, +almost, but there is one more: An |unset_node| has nearly the same format +as an |hlist_node| or |vlist_node|; it is used for entries in \.{\\halign} +or \.{\\valign} that are not yet in their final form, since the box +dimensions are their ``natural'' sizes before any glue adjustment has been +made. The |glue_set| word is not present; instead, we have a |glue_stretch| +field, which contains the total stretch of order |glue_order| that is +present in the hlist or vlist being boxed. +Similarly, the |shift_amount| field is replaced by a |glue_shrink| field, +containing the total shrink of order |glue_sign| that is present. +The |subtype| field is called |span_count|; an unset box typically +contains the data for |qo(span_count)+1| columns. +Unset nodes will be changed to box nodes when alignment is completed. + +@d unset_node 13 /*|type| for an unset node*/ +@d glue_stretch(A) mem[A+glue_offset].sc /*total stretch in an unset node*/ +@d glue_shrink(A) shift_amount(A) /*total shrink in an unset node*/ +@d span_count(A) subtype(A) /*indicates the number of spanned columns*/ + +@ In fact, there are still more types coming. When we get to math formula +processing we will see that a |style_node| has |type==14|; and a number +of larger type codes will also be defined, for use in math mode only. + +@ Warning: If any changes are made to these data structure layouts, such as +changing any of the node sizes or even reordering the words of nodes, +the |copy_node_list| procedure and the memory initialization code +below may have to be changed. Such potentially dangerous parts of the +program are listed in the index under `data structure assumptions'. +@!@^data structure assumptions@> +However, other references to the nodes are made symbolically in terms of +the \.{WEB} macro definitions above, so that format changes will leave +\TeX's other algorithms intact. +@^system dependencies@> + +@* Memory layout. +Some areas of |mem| are dedicated to fixed usage, since static allocation is +more efficient than dynamic allocation when we can get away with it. For +example, locations |mem_bot| to |mem_bot+3| are always used to store the +specification for glue that is `\.{0pt plus 0pt minus 0pt}'. The +following macro definitions accomplish the static allocation by giving +symbolic names to the fixed positions. Static variable-size nodes appear +in locations |mem_bot| through |lo_mem_stat_max|, and static single-word nodes +appear in locations |hi_mem_stat_min| through |mem_top|, inclusive. It is +harmless to let |lig_trick| and |garbage| share the same location of |mem|. + +@d zero_glue mem_bot /*specification for \.{0pt plus 0pt minus 0pt}*/ +@d fil_glue zero_glue+glue_spec_size /*\.{0pt plus 1fil minus 0pt}*/ +@d fill_glue fil_glue+glue_spec_size /*\.{0pt plus 1fill minus 0pt}*/ +@d ss_glue fill_glue+glue_spec_size /*\.{0pt plus 1fil minus 1fil}*/ +@d fil_neg_glue ss_glue+glue_spec_size /*\.{0pt plus -1fil minus 0pt}*/ +@d lo_mem_stat_max fil_neg_glue+glue_spec_size-1 /*largest statically + allocated word in the variable-size |mem|*/ +@# +@d page_ins_head mem_top /*list of insertion data for current page*/ +@d contrib_head mem_top-1 /*vlist of items not yet on current page*/ +@d page_head mem_top-2 /*vlist for current page*/ +@d temp_head mem_top-3 /*head of a temporary list of some kind*/ +@d hold_head mem_top-4 /*head of a temporary list of another kind*/ +@d adjust_head mem_top-5 /*head of adjustment list returned by |hpack|*/ +@d active mem_top-7 /*head of active list in |line_break|, needs two words*/ +@d align_head mem_top-8 /*head of preamble list for alignments*/ +@d end_span mem_top-9 /*tail of spanned-width lists*/ +@d omit_template mem_top-10 /*a constant token list*/ +@d null_list mem_top-11 /*permanently empty list*/ +@d lig_trick mem_top-12 /*a ligature masquerading as a |char_node|*/ +@d garbage mem_top-12 /*used for scrap information*/ +@d backup_head mem_top-13 /*head of token list built by |scan_keyword|*/ +@d hi_mem_stat_min mem_top-13 /*smallest statically allocated word in + the one-word |mem|*/ +@d hi_mem_stat_usage 14 /*the number of one-word nodes always present*/ + +@ The following code gets |mem| off to a good start, when \TeX\ is +initializing itself the slow~way. + +@= +int @!k; /*index into |mem|, |eqtb|, etc.*/ + +@ @= +for (k=mem_bot+1; k<=lo_mem_stat_max; k++) mem[k].sc=0; + /*all glue dimensions are zeroed*/ +@^data structure assumptions@> +k=mem_bot;@+while (k <= lo_mem_stat_max) + /*set first words of glue specifications*/ + {@+glue_ref_count(k)=null+1; + stretch_order(k)=normal;shrink_order(k)=normal; + k=k+glue_spec_size; + } +stretch(fil_glue)=unity;stretch_order(fil_glue)=fil;@/ +stretch(fill_glue)=unity;stretch_order(fill_glue)=fill;@/ +stretch(ss_glue)=unity;stretch_order(ss_glue)=fil;@/ +shrink(ss_glue)=unity;shrink_order(ss_glue)=fil;@/ +stretch(fil_neg_glue)=-unity;stretch_order(fil_neg_glue)=fil;@/ +rover=lo_mem_stat_max+1; +link(rover)=empty_flag; /*now initialize the dynamic memory*/ +node_size(rover)=1000; /*which is a 1000-word available node*/ +llink(rover)=rover;rlink(rover)=rover;@/ +lo_mem_max=rover+1000;link(lo_mem_max)=null;info(lo_mem_max)=null;@/ +for (k=hi_mem_stat_min; k<=mem_top; k++) + mem[k]=mem[lo_mem_max]; /*clear list heads*/ +@; +avail=null;mem_end=mem_top; +hi_mem_min=hi_mem_stat_min; /*initialize the one-word memory*/ +var_used=lo_mem_stat_max+1-mem_bot;dyn_used=hi_mem_stat_usage; + /*initialize statistics*/ + +@ If \TeX\ is extended improperly, the |mem| array might get screwed up. +For example, some pointers might be wrong, or some ``dead'' nodes might not +have been freed when the last reference to them disappeared. Procedures +|check_mem| and |search_mem| are available to help diagnose such +problems. These procedures make use of two arrays called |is_free| and +|was_free| that are present only if \TeX's debugging routines have +been included. (You may want to decrease the size of |mem| while you +@^debugging@> +are debugging.) + +@= +#ifdef @!DEBUG +static bool @!is_free0[mem_max-mem_min+1], + *const @!is_free = @!is_free0-mem_min; /*free cells*/ +@t\hskip10pt@>static bool @!was_free0[mem_max-mem_min+1], + *const @!was_free = @!was_free0-mem_min; + /*previously free cells*/ +@t\hskip10pt@>static pointer @!was_mem_end, @!was_lo_max, @!was_hi_min; + /*previous |mem_end|, |lo_mem_max|, and |hi_mem_min|*/ +@t\hskip10pt@>static bool @!panicking; /*do we want to check memory constantly?*/ +#endif + +@ @= +#ifdef @!DEBUG +was_mem_end=mem_min; /*indicate that everything was previously free*/ +was_lo_max=mem_min;was_hi_min=mem_max; +panicking=false; +#endif + +@ Procedure |check_mem| makes sure that the available space lists of +|mem| are well formed, and it optionally prints out all locations +that are reserved now but were free the last time this procedure was called. + +@p +#ifdef @!DEBUG +static void check_mem(bool @!print_locs) +{@+ /*loop exits*/ +int p, @!q; /*current locations of interest in |mem|*/ +bool @!clobbered; /*is something amiss?*/ +for (p=mem_min; p<=lo_mem_max; p++) is_free[p]=false; /*you can probably + do this faster*/ +for (p=hi_mem_min; p<=mem_end; p++) is_free[p]=false; /*ditto*/ +@; +@; +@; +if (print_locs) @; +for (p=mem_min; p<=lo_mem_max; p++) was_free[p]=is_free[p]; +for (p=hi_mem_min; p<=mem_end; p++) was_free[p]=is_free[p]; + /*|was_free=is_free| might be faster*/ +was_mem_end=mem_end;was_lo_max=lo_mem_max;was_hi_min=hi_mem_min; +} +#endif + +@ @= +p=avail;q=null;clobbered=false; +while (p!=null) + {@+if ((p > mem_end)||(p < hi_mem_min)) clobbered=true; + else if (is_free[p]) clobbered=true; + if (clobbered) + {@+print_nl("AVAIL list clobbered at "); +@.AVAIL list clobbered...@> + print_int(q);goto done1; + } + is_free[p]=true;q=p;p=link(q); + } +done1: + +@ @= +p=rover;q=null;clobbered=false; +@/do@+{if ((p >= lo_mem_max)||(p < mem_min)) clobbered=true; + else if ((rlink(p) >= lo_mem_max)||(rlink(p) < mem_min)) clobbered=true; + else if (!(is_empty(p))||(node_size(p) < 2)||@| + (p+node_size(p) > lo_mem_max)||@|(llink(rlink(p))!=p)) clobbered=true; + if (clobbered) + {@+print_nl("Double-AVAIL list clobbered at "); + print_int(q);goto done2; + } +for (q=p; q<=p+node_size(p)-1; q++) /*mark all locations free*/ + {@+if (is_free[q]) + {@+print_nl("Doubly free location at "); +@.Doubly free location...@> + print_int(q);goto done2; + } + is_free[q]=true; + } +q=p;p=rlink(p); +}@+ while (!(p==rover)); +done2: + +@ @= +p=mem_min; +while (p <= lo_mem_max) /*node |p| should not be empty*/ + {@+if (is_empty(p)) + {@+print_nl("Bad flag at ");print_int(p); +@.Bad flag...@> + } + while ((p <= lo_mem_max)&&!is_free[p]) incr(p); + while ((p <= lo_mem_max)&&is_free[p]) incr(p); + } + +@ @= +{@+print_nl("New busy locs:"); +for (p=mem_min; p<=lo_mem_max; p++) + if (!is_free[p]&&((p > was_lo_max)||was_free[p])) + {@+print_char(' ');print_int(p); + } +for (p=hi_mem_min; p<=mem_end; p++) + if (!is_free[p]&& + ((p < was_hi_min)||(p > was_mem_end)||was_free[p])) + {@+print_char(' ');print_int(p); + } +} + +@ The |search_mem| procedure attempts to answer the question ``Who points +to node~|p|?'' In doing so, it fetches |link| and |info| fields of |mem| +that might not be of type |two_halves|. Strictly speaking, this is +@^dirty \PASCAL@> +undefined in \PASCAL, and it can lead to ``false drops'' (words that seem to +point to |p| purely by coincidence). But for debugging purposes, we want +to rule out the places that do {\sl not\/} point to |p|, so a few false +drops are tolerable. + +@p +#ifdef @!DEBUG +static void search_mem(pointer @!p) /*look for pointers to |p|*/ +{@+int q; /*current position being searched*/ +for (q=mem_min; q<=lo_mem_max; q++) + {@+if (link(q)==p) + {@+print_nl("LINK(");print_int(q);print_char(')'); + } + if (info(q)==p) + {@+print_nl("INFO(");print_int(q);print_char(')'); + } + } +for (q=hi_mem_min; q<=mem_end; q++) + {@+if (link(q)==p) + {@+print_nl("LINK(");print_int(q);print_char(')'); + } + if (info(q)==p) + {@+print_nl("INFO(");print_int(q);print_char(')'); + } + } +@; +@; +@; +} +#endif + +@* Displaying boxes. +We can reinforce our knowledge of the data structures just introduced +by considering two procedures that display a list in symbolic form. +The first of these, called |short_display|, is used in ``overfull box'' +messages to give the top-level description of a list. The other one, +called |show_node_list|, prints a detailed description of exactly what +is in the data structure. + +The philosophy of |short_display| is to ignore the fine points about exactly +what is inside boxes, except that ligatures and discretionary breaks are +expanded. As a result, |short_display| is a recursive procedure, but the +recursion is never more than one level deep. +@^recursion@> + +A global variable |font_in_short_display| keeps track of the font code that +is assumed to be present when |short_display| begins; deviations from this +font will be printed. + +@= +static int @!font_in_short_display; /*an internal font number*/ + +@ Boxes, rules, inserts, whatsits, marks, and things in general that are +sort of ``complicated'' are indicated only by printing `\.{[]}'. + +@p static void short_display(int @!p) /*prints highlights of list |p|*/ +{@+int n; /*for replacement counts*/ +while (p > mem_min) + {@+if (is_char_node(p)) + {@+if (p <= mem_end) + {@+if (font(p)!=font_in_short_display) + {@+if ((font(p) < font_base)||(font(p) > font_max)) + print_char('*'); +@.*\relax@> + else@; + print_char(' ');font_in_short_display=font(p); + } + print_ASCII(qo(character(p))); + } + } + else@; + p=link(p); + } +} + +@ @= +switch (type(p)) { +case hlist_node: case vlist_node: case ins_node: + case whatsit_node: case mark_node: case adjust_node: + case unset_node: print("[]");@+break; +case rule_node: print_char('|');@+break; +case glue_node: if (glue_ptr(p)!=zero_glue) print_char(' ');@+break; +case math_node: print_char('$');@+break; +case ligature_node: short_display(lig_ptr(p));@+break; +case disc_node: {@+short_display(pre_break(p)); + short_display(post_break(p));@/ + n=replace_count(p); + while (n > 0) + {@+if (link(p)!=null) p=link(p); + decr(n); + } + } @+break; +default:do_nothing; +} + +@ The |show_node_list| routine requires some auxiliary subroutines: one to +print a font-and-character combination, one to print a token list without +its reference count, and one to print a rule dimension. + +@p static void print_font_and_char(int @!p) /*prints |char_node| data*/ +{@+if (p > mem_end) print_esc("CLOBBERED."); +else{@+if ((font(p) < font_base)||(font(p) > font_max)) print_char('*'); +@.*\relax@> + else@; + print_char(' ');print_ASCII(qo(character(p))); + } +} +@# +static void print_mark(int @!p) /*prints token list data in braces*/ +{@+print_char('{'); +if ((p < hi_mem_min)||(p > mem_end)) print_esc("CLOBBERED."); +else show_token_list(link(p), null, max_print_line-10); +print_char('}'); +} +@# +static void print_rule_dimen(scaled @!d) /*prints dimension in rule node*/ +{@+if (is_running(d)) print_char('*');else print_scaled(d); +@.*\relax@> +} + +@ Then there is a subroutine that prints glue stretch and shrink, possibly +followed by the name of finite units: + +@p static void print_glue(scaled @!d, int @!order, char *@!s) + /*prints a glue component*/ +{@+print_scaled(d); +if ((order < normal)||(order > filll)) print("foul"); +else if (order > normal) + {@+print("fil"); + while (order > fil) + {@+print_char('l');decr(order); + } + } +else if (s!=0) print(s); +} + +@ The next subroutine prints a whole glue specification. + +@p static void print_spec(int @!p, char *@!s) + /*prints a glue specification*/ +{@+if ((p < mem_min)||(p >= lo_mem_max)) print_char('*'); +@.*\relax@> +else{@+print_scaled(width(p)); + if (s!=0) print(s); + if (stretch(p)!=0) + {@+print(" plus ");print_glue(stretch(p), stretch_order(p), s); + } + if (shrink(p)!=0) + {@+print(" minus ");print_glue(shrink(p), shrink_order(p), s); + } + } +} + +@ We also need to declare some procedures that appear later in this +documentation. + +@p @@; +@@; + +@ Since boxes can be inside of boxes, |show_node_list| is inherently recursive, +@^recursion@> +up to a given maximum number of levels. The history of nesting is indicated +by the current string, which will be printed at the beginning of each line; +the length of this string, namely |cur_length|, is the depth of nesting. + +Recursive calls on |show_node_list| therefore use the following pattern: + +@d node_list_display(A) + {@+append_char('.');show_node_list(A);flush_char; + } /*|str_room| need not be checked; see |show_box| below*/ + +@ A global variable called |depth_threshold| is used to record the maximum +depth of nesting for which |show_node_list| will show information. If we +have |depth_threshold==0|, for example, only the top level information will +be given and no sublists will be traversed. Another global variable, called +|breadth_max|, tells the maximum number of items to show at each level; +|breadth_max| had better be positive, or you won't see anything. + +@= +static int @!depth_threshold; /*maximum nesting depth in box displays*/ +static int @!breadth_max; /*maximum number of items shown at the same list level*/ + +@ Now we are ready for |show_node_list| itself. This procedure has been +written to be ``extra robust'' in the sense that it should not crash or get +into a loop even if the data structures have been messed up by bugs in +the rest of the program. You can safely call its parent routine +|show_box(p)| for arbitrary values of |p| when you are debugging \TeX. +However, in the presence of bad data, the procedure may +@^dirty \PASCAL@>@^debugging@> +fetch a |memory_word| whose variant is different from the way it was stored; +for example, it might try to read |mem[p].hh| when |mem[p]| +contains a scaled integer, if |p| is a pointer that has been +clobbered or chosen at random. + +@p static void show_node_list(int @!p) /*prints a node list symbolically*/ +{@+ +int n; /*the number of items already printed at this level*/ +double @!g; /*a glue ratio, as a floating point number*/ +if (cur_length > depth_threshold) + {@+if (p > null) print(" []"); + /*indicate that there's been some truncation*/ + return; + } +n=0; +while (p > mem_min) + {@+print_ln();print_current_string(); /*display the nesting history*/ + if (p > mem_end) /*pointer out of range*/ + {@+print("Bad link, display aborted.");return; +@.Bad link...@> + } + incr(n);if (n > breadth_max) /*time to stop*/ + {@+print("etc.");return; +@.etc@> + } + @; + p=link(p); + } + +} + +@ @= +if (is_char_node(p)) print_font_and_char(p); +else switch (type(p)) { + case hlist_node: case vlist_node: case unset_node: @@;@+break; + case rule_node: @@;@+break; + case ins_node: @@;@+break; + case whatsit_node: @@;@+break; + case glue_node: @@;@+break; + case kern_node: @@;@+break; + case math_node: @@;@+break; + case ligature_node: @@;@+break; + case penalty_node: @@;@+break; + case disc_node: @@;@+break; + case mark_node: @@;@+break; + case adjust_node: @@;@+break; + @t\4@>@@; + default:print("Unknown node type!"); + } + +@ @= +{@+if (type(p)==hlist_node) print_esc("h"); +else if (type(p)==vlist_node) print_esc("v"); +else print_esc("unset"); +print("box(");print_scaled(height(p));print_char('+'); +print_scaled(depth(p));print(")x");print_scaled(width(p)); +if (type(p)==unset_node) + @@; +else{@+@; + if (shift_amount(p)!=0) + {@+print(", shifted ");print_scaled(shift_amount(p)); + } + } +node_list_display(list_ptr(p)); /*recursive call*/ +} + +@ @= +{@+if (span_count(p)!=min_quarterword) + {@+print(" (");print_int(qo(span_count(p))+1); + print(" columns)"); + } +if (glue_stretch(p)!=0) + {@+print(", stretch ");print_glue(glue_stretch(p), glue_order(p), 0); + } +if (glue_shrink(p)!=0) + {@+print(", shrink ");print_glue(glue_shrink(p), glue_sign(p), 0); + } +} + +@ The code will have to change in this place if |glue_ratio| is +a structured type instead of an ordinary |double|. Note that this routine +should avoid arithmetic errors even if the |glue_set| field holds an +arbitrary random value. The following code assumes that a properly +formed nonzero |double| number has absolute value $2^{20}$ or more when +it is regarded as an integer; this precaution was adequate to prevent +floating point underflow on the author's computer. +@^system dependencies@> +@^dirty \PASCAL@> + +@= +g=unfix(glue_set(p)); +if ((g!=float_constant(0))&&(glue_sign(p)!=normal)) + {@+print(", glue set "); + if (glue_sign(p)==shrinking) print("- "); + if (abs(mem[p+glue_offset].i) < 04000000) print("?.?"); + else if (abs(g) > float_constant(20000)) + {@+if (g > float_constant(0)) print_char('>'); + else print("< -"); + print_glue(20000*unity, glue_order(p), 0); + } + else print_glue(round(unity*g), glue_order(p), 0); +@^real multiplication@> + } + +@ @= +{@+print_esc("rule(");print_rule_dimen(height(p));print_char('+'); +print_rule_dimen(depth(p));print(")x");print_rule_dimen(width(p)); +} + +@ @= +{@+print_esc("insert");print_int(qo(subtype(p))); +print(", natural size ");print_scaled(height(p)); +print("; split(");print_spec(split_top_ptr(p), 0); +print_char(',');print_scaled(depth(p)); +print("); float cost ");print_int(float_cost(p)); +node_list_display(ins_ptr(p)); /*recursive call*/ +} + +@ @= +if (subtype(p) >= a_leaders) @@; +else{@+print_esc("glue"); + if (subtype(p)!=normal) + {@+print_char('('); + if (subtype(p) < cond_math_glue) + print_skip_param(subtype(p)-1); + else if (subtype(p)==cond_math_glue) print_esc("nonscript"); + else print_esc("mskip"); + print_char(')'); + } + if (subtype(p)!=cond_math_glue) + {@+print_char(' '); + if (subtype(p) < cond_math_glue) print_spec(glue_ptr(p), 0); + else print_spec(glue_ptr(p),"mu"); + } + } + +@ @= +{@+print_esc(""); +if (subtype(p)==c_leaders) print_char('c'); +else if (subtype(p)==x_leaders) print_char('x'); +print("leaders ");print_spec(glue_ptr(p), 0); +node_list_display(leader_ptr(p)); /*recursive call*/ +} + +@ An ``explicit'' kern value is indicated implicitly by an explicit space. + +@= +if (subtype(p)!=mu_glue) + {@+print_esc("kern"); + if (subtype(p)!=normal) print_char(' '); + print_scaled(width(p)); + if (subtype(p)==acc_kern) print(" (for accent)"); +@.for accent@> + } +else{@+print_esc("mkern");print_scaled(width(p));print("mu"); + } + +@ @= +{@+print_esc("math"); +if (subtype(p)==before) print("on"); +else print("off"); +if (width(p)!=0) + {@+print(", surrounded ");print_scaled(width(p)); + } +} + +@ @= +{@+print_font_and_char(lig_char(p));print(" (ligature "); +if (subtype(p) > 1) print_char('|'); +font_in_short_display=font(lig_char(p));short_display(lig_ptr(p)); +if (odd(subtype(p))) print_char('|'); +print_char(')'); +} + +@ @= +{@+print_esc("penalty ");print_int(penalty(p)); +} + +@ The |post_break| list of a discretionary node is indicated by a prefixed +`\.{\char'174}' instead of the `\..' before the |pre_break| list. + +@= +{@+print_esc("discretionary"); +if (replace_count(p) > 0) + {@+print(" replacing ");print_int(replace_count(p)); + } +node_list_display(pre_break(p)); /*recursive call*/ +append_char('|');show_node_list(post_break(p));flush_char; /*recursive call*/ +} + +@ @= +{@+print_esc("mark"); +if (mark_class(p)!=0) + {@+print_char('s');print_int(mark_class(p)); + } +print_mark(mark_ptr(p)); +} + +@ @= +{@+print_esc("vadjust");node_list_display(adjust_ptr(p)); /*recursive call*/ +} + +@ The recursive machinery is started by calling |show_box|. +@^recursion@> + +@p static void show_box(pointer @!p) +{@+@; +if (breadth_max <= 0) breadth_max=5; +if (pool_ptr+depth_threshold >= pool_size) + depth_threshold=pool_size-pool_ptr-1; + /*now there's enough room for prefix string*/ +show_node_list(p); /*the show starts at |p|*/ +print_ln(); +} + +@* Destroying boxes. +When we are done with a node list, we are obliged to return it to free +storage, including all of its sublists. The recursive procedure +|flush_node_list| does this for us. + +@ First, however, we shall consider two non-recursive procedures that do +simpler tasks. The first of these, |delete_token_ref|, is called when +a pointer to a token list's reference count is being removed. This means +that the token list should disappear if the reference count was |null|, +otherwise the count should be decreased by one. +@^reference counts@> + +@d token_ref_count(A) info(A) /*reference count preceding a token list*/ + +@p static void delete_token_ref(pointer @!p) /*|p| points to the reference count + of a token list that is losing one reference*/ +{@+if (token_ref_count(p)==null) flush_list(p); +else decr(token_ref_count(p)); +} + +@ Similarly, |delete_glue_ref| is called when a pointer to a glue +specification is being withdrawn. +@^reference counts@> +@d fast_delete_glue_ref(A) @t@>@;@/ + {@+if (glue_ref_count(A)==null) free_node(A, glue_spec_size); + else decr(glue_ref_count(A)); + } + +@p static void delete_glue_ref(pointer @!p) /*|p| points to a glue specification*/ +fast_delete_glue_ref(p) + +@ Now we are ready to delete any node list, recursively. +In practice, the nodes deleted are usually charnodes (about 2/3 of the time), +and they are glue nodes in about half of the remaining cases. +@^recursion@> + +@p static void flush_node_list(pointer @!p) /*erase list of nodes starting at |p|*/ +{@+ /*go here when node |p| has been freed*/ +pointer q; /*successor to node |p|*/ +while (p!=null) +@^inner loop@> + {@+q=link(p); + if (is_char_node(p)) free_avail(p)@; + else{@+switch (type(p)) { + case hlist_node: case vlist_node: + case unset_node: {@+flush_node_list(list_ptr(p)); + free_node(p, box_node_size);goto done; + } + case rule_node: {@+free_node(p, rule_node_size);goto done; + } + case ins_node: {@+flush_node_list(ins_ptr(p)); + delete_glue_ref(split_top_ptr(p)); + free_node(p, ins_node_size);goto done; + } + case whatsit_node: @@; + case glue_node: {@+fast_delete_glue_ref(glue_ptr(p)); + if (leader_ptr(p)!=null) flush_node_list(leader_ptr(p)); + } @+break; + case kern_node: case math_node: case penalty_node: do_nothing;@+break; + case ligature_node: flush_node_list(lig_ptr(p));@+break; + case mark_node: delete_token_ref(mark_ptr(p));@+break; + case disc_node: {@+flush_node_list(pre_break(p)); + flush_node_list(post_break(p)); + } @+break; + case adjust_node: flush_node_list(adjust_ptr(p));@+break; + @t\4@>@@; + default:confusion("flushing"); +@:this can't happen flushing}{\quad flushing@> + } @/ + free_node(p, small_node_size); + done: ;} + p=q; + } +} + +@* Copying boxes. +Another recursive operation that acts on boxes is sometimes needed: The +procedure |copy_node_list| returns a pointer to another node list that has +the same structure and meaning as the original. Note that since glue +specifications and token lists have reference counts, we need not make +copies of them. Reference counts can never get too large to fit in a +halfword, since each pointer to a node is in a different memory address, +and the total number of memory addresses fits in a halfword. +@^recursion@> +@^reference counts@> + +(Well, there actually are also references from outside |mem|; if the +|save_stack| is made arbitrarily large, it would theoretically be possible +to break \TeX\ by overflowing a reference count. But who would want to do that?) + +@d add_token_ref(A) incr(token_ref_count(A)) /*new reference to a token list*/ +@d add_glue_ref(A) incr(glue_ref_count(A)) /*new reference to a glue spec*/ + +@ The copying procedure copies words en masse without bothering +to look at their individual fields. If the node format changes---for +example, if the size is altered, or if some link field is moved to another +relative position---then this code may need to be changed too. +@^data structure assumptions@> + +@p static pointer copy_node_list(pointer @!p) /*makes a duplicate of the + node list that starts at |p| and returns a pointer to the new list*/ +{@+pointer h; /*temporary head of copied list*/ +pointer @!q; /*previous position in new list*/ +pointer @!r; /*current node being fabricated for new list*/ +int @!words; /*number of words remaining to be copied*/ +h=get_avail();q=h; +while (p!=null) + {@+@; + link(q)=r;q=r;p=link(p); + } +link(q)=null;q=link(h);free_avail(h); +return q; +} + +@ @= +words=1; /*this setting occurs in more branches than any other*/ +if (is_char_node(p)) r=get_avail(); +else@; +while (words > 0) + {@+decr(words);mem[r+words]=mem[p+words]; + } + +@ @= +switch (type(p)) { +case hlist_node: case vlist_node: case unset_node: {@+r=get_node(box_node_size); + mem[r+6]=mem[p+6];mem[r+5]=mem[p+5]; /*copy the last two words*/ + list_ptr(r)=copy_node_list(list_ptr(p)); /*this affects |mem[r+5]|*/ + words=5; + } @+break; +case rule_node: {@+r=get_node(rule_node_size);words=rule_node_size; + } @+break; +case ins_node: {@+r=get_node(ins_node_size);mem[r+4]=mem[p+4]; + add_glue_ref(split_top_ptr(p)); + ins_ptr(r)=copy_node_list(ins_ptr(p)); /*this affects |mem[r+4]|*/ + words=ins_node_size-1; + } @+break; +case whatsit_node: @@;@+break; +case glue_node: {@+r=get_node(small_node_size);add_glue_ref(glue_ptr(p)); + glue_ptr(r)=glue_ptr(p);leader_ptr(r)=copy_node_list(leader_ptr(p)); + } @+break; +case kern_node: case math_node: case penalty_node: {@+r=get_node(small_node_size); + words=small_node_size; + } @+break; +case ligature_node: {@+r=get_node(small_node_size); + mem[lig_char(r)]=mem[lig_char(p)]; /*copy |font| and |character|*/ + lig_ptr(r)=copy_node_list(lig_ptr(p)); + } @+break; +case disc_node: {@+r=get_node(small_node_size); + pre_break(r)=copy_node_list(pre_break(p)); + post_break(r)=copy_node_list(post_break(p)); + } @+break; +case mark_node: {@+r=get_node(small_node_size);add_token_ref(mark_ptr(p)); + words=small_node_size; + } @+break; +case adjust_node: {@+r=get_node(small_node_size); + adjust_ptr(r)=copy_node_list(adjust_ptr(p)); + } @+break; /*|words==1==small_node_size-1|*/ +default:confusion("copying"); +@:this can't happen copying}{\quad copying@> +} + +@* The command codes. +Before we can go any further, we need to define symbolic names for the internal +code numbers that represent the various commands obeyed by \TeX. These codes +are somewhat arbitrary, but not completely so. For example, the command +codes for character types are fixed by the language, since a user says, +e.g., `\.{\\catcode \`\\\${} = 3}' to make \.{\char'44} a math delimiter, +and the command code |math_shift| is equal to~3. Some other codes have +been made adjacent so that |case| statements in the program need not consider +cases that are widely spaced, or so that |case| statements can be replaced +by |if| statements. + +At any rate, here is the list, for future reference. First come the +``catcode'' commands, several of which share their numeric codes with +ordinary commands when the catcode cannot emerge from \TeX's scanning routine. + +@d escape 0 /*escape delimiter (called \.\\ in {\sl The \TeX book\/})*/ +@:TeXbook}{\sl The \TeX book@> +@d relax 0 /*do nothing ( \.{\\relax} )*/ +@d left_brace 1 /*beginning of a group ( \.\{ )*/ +@d right_brace 2 /*ending of a group ( \.\} )*/ +@d math_shift 3 /*mathematics shift character ( \.\$ )*/ +@d tab_mark 4 /*alignment delimiter ( \.\&, \.{\\span} )*/ +@d car_ret 5 /*end of line ( |carriage_return|, \.{\\cr}, \.{\\crcr} )*/ +@d out_param 5 /*output a macro parameter*/ +@d mac_param 6 /*macro parameter symbol ( \.\# )*/ +@d sup_mark 7 /*superscript ( \.{\char'136} )*/ +@d sub_mark 8 /*subscript ( \.{\char'137} )*/ +@d ignore 9 /*characters to ignore ( \.{\^\^@@} )*/ +@d endv 9 /*end of \ list in alignment template*/ +@d spacer 10 /*characters equivalent to blank space ( \.{\ } )*/ +@d letter 11 /*characters regarded as letters ( \.{A..Z}, \.{a..z} )*/ +@d other_char 12 /*none of the special character types*/ +@d active_char 13 /*characters that invoke macros ( \.{\char`\~} )*/ +@d par_end 13 /*end of paragraph ( \.{\\par} )*/ +@d match 13 /*match a macro parameter*/ +@d comment 14 /*characters that introduce comments ( \.\% )*/ +@d end_match 14 /*end of parameters to macro*/ +@d stop 14 /*end of job ( \.{\\end}, \.{\\dump} )*/ +@d invalid_char 15 /*characters that shouldn't appear ( \.{\^\^?} )*/ +@d delim_num 15 /*specify delimiter numerically ( \.{\\delimiter} )*/ +@d max_char_code 15 /*largest catcode for individual characters*/ + +@ Next are the ordinary run-of-the-mill command codes. Codes that are +|min_internal| or more represent internal quantities that might be +expanded by `\.{\\the}'. + +@d char_num 16 /*character specified numerically ( \.{\\char} )*/ +@d math_char_num 17 /*explicit math code ( \.{\\mathchar} )*/ +@d mark 18 /*mark definition ( \.{\\mark} )*/ +@d xray 19 /*peek inside of \TeX\ ( \.{\\show}, \.{\\showbox}, etc.~)*/ +@d make_box 20 /*make a box ( \.{\\box}, \.{\\copy}, \.{\\hbox}, etc.~)*/ +@d hmove 21 /*horizontal motion ( \.{\\moveleft}, \.{\\moveright} )*/ +@d vmove 22 /*vertical motion ( \.{\\raise}, \.{\\lower} )*/ +@d un_hbox 23 /*unglue a box ( \.{\\unhbox}, \.{\\unhcopy} )*/ +@d un_vbox 24 /*unglue a box ( \.{\\unvbox}, \.{\\unvcopy} )*/ + /*( or \.{\\pagediscards}, \.{\\splitdiscards} )*/ +@d remove_item 25 /*nullify last item ( \.{\\unpenalty}, + \.{\\unkern}, \.{\\unskip} )*/ +@d hskip 26 /*horizontal glue ( \.{\\hskip}, \.{\\hfil}, etc.~)*/ +@d vskip 27 /*vertical glue ( \.{\\vskip}, \.{\\vfil}, etc.~)*/ +@d mskip 28 /*math glue ( \.{\\mskip} )*/ +@d kern 29 /*fixed space ( \.{\\kern} )*/ +@d mkern 30 /*math kern ( \.{\\mkern} )*/ +@d leader_ship 31 /*use a box ( \.{\\shipout}, \.{\\leaders}, etc.~)*/ +@d halign 32 /*horizontal table alignment ( \.{\\halign} )*/ +@d valign 33 /*vertical table alignment ( \.{\\valign} )*/ +@d no_align 34 /*temporary escape from alignment ( \.{\\noalign} )*/ +@d vrule 35 /*vertical rule ( \.{\\vrule} )*/ +@d hrule 36 /*horizontal rule ( \.{\\hrule} )*/ +@d insert 37 /*vlist inserted in box ( \.{\\insert} )*/ +@d vadjust 38 /*vlist inserted in enclosing paragraph ( \.{\\vadjust} )*/ +@d ignore_spaces 39 /*gobble |spacer| tokens ( \.{\\ignorespaces} )*/ +@d after_assignment 40 /*save till assignment is done ( \.{\\afterassignment} )*/ +@d after_group 41 /*save till group is done ( \.{\\aftergroup} )*/ +@d break_penalty 42 /*additional badness ( \.{\\penalty} )*/ +@d start_par 43 /*begin paragraph ( \.{\\indent}, \.{\\noindent} )*/ +@d ital_corr 44 /*italic correction ( \.{\\/} )*/ +@d accent 45 /*attach accent in text ( \.{\\accent} )*/ +@d math_accent 46 /*attach accent in math ( \.{\\mathaccent} )*/ +@d discretionary 47 /*discretionary texts ( \.{\\-}, \.{\\discretionary} )*/ +@d eq_no 48 /*equation number ( \.{\\eqno}, \.{\\leqno} )*/ +@d left_right 49 /*variable delimiter ( \.{\\left}, \.{\\right} )*/ + /*( or \.{\\middle} )*/ +@d math_comp 50 /*component of formula ( \.{\\mathbin}, etc.~)*/ +@d limit_switch 51 /*diddle limit conventions ( \.{\\displaylimits}, etc.~)*/ +@d above 52 /*generalized fraction ( \.{\\above}, \.{\\atop}, etc.~)*/ +@d math_style 53 /*style specification ( \.{\\displaystyle}, etc.~)*/ +@d math_choice 54 /*choice specification ( \.{\\mathchoice} )*/ +@d non_script 55 /*conditional math glue ( \.{\\nonscript} )*/ +@d vcenter 56 /*vertically center a vbox ( \.{\\vcenter} )*/ +@d case_shift 57 /*force specific case ( \.{\\lowercase}, \.{\\uppercase}~)*/ +@d message 58 /*send to user ( \.{\\message}, \.{\\errmessage} )*/ +@d extension 59 /*extensions to \TeX\ ( \.{\\write}, \.{\\special}, etc.~)*/ +@d in_stream 60 /*files for reading ( \.{\\openin}, \.{\\closein} )*/ +@d begin_group 61 /*begin local grouping ( \.{\\begingroup} )*/ +@d end_group 62 /*end local grouping ( \.{\\endgroup} )*/ +@d omit 63 /*omit alignment template ( \.{\\omit} )*/ +@d ex_space 64 /*explicit space ( \.{\\\ } )*/ +@d no_boundary 65 /*suppress boundary ligatures ( \.{\\noboundary} )*/ +@d radical 66 /*square root and similar signs ( \.{\\radical} )*/ +@d end_cs_name 67 /*end control sequence ( \.{\\endcsname} )*/ +@d min_internal 68 /*the smallest code that can follow \.{\\the}*/ +@d char_given 68 /*character code defined by \.{\\chardef}*/ +@d math_given 69 /*math code defined by \.{\\mathchardef}*/ +@d last_item 70 /*most recent item ( \.{\\lastpenalty}, + \.{\\lastkern}, \.{\\lastskip} )*/ +@d max_non_prefixed_command 70 /*largest command code that can't be \.{\\global}*/ + +@ The next codes are special; they all relate to mode-independent +assignment of values to \TeX's internal registers or tables. +Codes that are |max_internal| or less represent internal quantities +that might be expanded by `\.{\\the}'. + +@d toks_register 71 /*token list register ( \.{\\toks} )*/ +@d assign_toks 72 /*special token list ( \.{\\output}, \.{\\everypar}, etc.~)*/ +@d assign_int 73 /*user-defined integer ( \.{\\tolerance}, \.{\\day}, etc.~)*/ +@d assign_dimen 74 /*user-defined length ( \.{\\hsize}, etc.~)*/ +@d assign_glue 75 /*user-defined glue ( \.{\\baselineskip}, etc.~)*/ +@d assign_mu_glue 76 /*user-defined muglue ( \.{\\thinmuskip}, etc.~)*/ +@d assign_font_dimen 77 /*user-defined font dimension ( \.{\\fontdimen} )*/ +@d assign_font_int 78 /*user-defined font integer ( \.{\\hyphenchar}, + \.{\\skewchar} )*/ +@d set_aux 79 /*specify state info ( \.{\\spacefactor}, \.{\\prevdepth} )*/ +@d set_prev_graf 80 /*specify state info ( \.{\\prevgraf} )*/ +@d set_page_dimen 81 /*specify state info ( \.{\\pagegoal}, etc.~)*/ +@d set_page_int 82 /*specify state info ( \.{\\deadcycles}, + \.{\\insertpenalties} )*/ + /*( or \.{\\interactionmode} )*/ +@d set_box_dimen 83 /*change dimension of box ( \.{\\wd}, \.{\\ht}, \.{\\dp} )*/ +@d set_shape 84 /*specify fancy paragraph shape ( \.{\\parshape} )*/ + /*(or \.{\\interlinepenalties}, etc.~)*/ +@d def_code 85 /*define a character code ( \.{\\catcode}, etc.~)*/ +@d def_family 86 /*declare math fonts ( \.{\\textfont}, etc.~)*/ +@d set_font 87 /*set current font ( font identifiers )*/ +@d def_font 88 /*define a font file ( \.{\\font} )*/ +@d internal_register 89 /*internal register ( \.{\\count}, \.{\\dimen}, etc.~)*/ +@d max_internal 89 /*the largest code that can follow \.{\\the}*/ +@d advance 90 /*advance a register or parameter ( \.{\\advance} )*/ +@d multiply 91 /*multiply a register or parameter ( \.{\\multiply} )*/ +@d divide 92 /*divide a register or parameter ( \.{\\divide} )*/ +@d prefix 93 /*qualify a definition ( \.{\\global}, \.{\\long}, \.{\\outer} )*/ + /*( or \.{\\protected} )*/ +@d let 94 /*assign a command code ( \.{\\let}, \.{\\futurelet} )*/ +@d shorthand_def 95 /*code definition ( \.{\\chardef}, \.{\\countdef}, etc.~)*/ +@d read_to_cs 96 /*read into a control sequence ( \.{\\read} )*/ + /*( or \.{\\readline} )*/ +@d def 97 /*macro definition ( \.{\\def}, \.{\\gdef}, \.{\\xdef}, \.{\\edef} )*/ +@d set_box 98 /*set a box ( \.{\\setbox} )*/ +@d hyph_data 99 /*hyphenation data ( \.{\\hyphenation}, \.{\\patterns} )*/ +@d set_interaction 100 /*define level of interaction ( \.{\\batchmode}, etc.~)*/ +@d max_command 100 /*the largest command code seen at |big_switch|*/ + +@ The remaining command codes are extra special, since they cannot get through +\TeX's scanner to the main control routine. They have been given values higher +than |max_command| so that their special nature is easily discernible. +The ``expandable'' commands come first. + +@d undefined_cs (max_command+1) /*initial state of most |eq_type| fields*/ +@d expand_after (max_command+2) /*special expansion ( \.{\\expandafter} )*/ +@d no_expand (max_command+3) /*special nonexpansion ( \.{\\noexpand} )*/ +@d input (max_command+4) /*input a source file ( \.{\\input}, \.{\\endinput} )*/ + /*( or \.{\\scantokens} )*/ +@d if_test (max_command+5) /*conditional text ( \.{\\if}, \.{\\ifcase}, etc.~)*/ +@d fi_or_else (max_command+6) /*delimiters for conditionals ( \.{\\else}, etc.~)*/ +@d cs_name (max_command+7) /*make a control sequence from tokens ( \.{\\csname} )*/ +@d convert (max_command+8) /*convert to text ( \.{\\number}, \.{\\string}, etc.~)*/ +@d the (max_command+9) /*expand an internal quantity ( \.{\\the} )*/ + /*( or \.{\\unexpanded}, \.{\\detokenize} )*/ +@d top_bot_mark (max_command+10) /*inserted mark ( \.{\\topmark}, etc.~)*/ +@d call (max_command+11) /*non-long, non-outer control sequence*/ +@d long_call (max_command+12) /*long, non-outer control sequence*/ +@d outer_call (max_command+13) /*non-long, outer control sequence*/ +@d long_outer_call (max_command+14) /*long, outer control sequence*/ +@d end_template (max_command+15) /*end of an alignment template*/ +@d dont_expand (max_command+16) /*the following token was marked by \.{\\noexpand}*/ +@d glue_ref (max_command+17) /*the equivalent points to a glue specification*/ +@d shape_ref (max_command+18) /*the equivalent points to a parshape specification*/ +@d box_ref (max_command+19) /*the equivalent points to a box node, or is |null|*/ +@d data (max_command+20) /*the equivalent is simply a halfword number*/ + +@* The semantic nest. +\TeX\ is typically in the midst of building many lists at once. For example, +when a math formula is being processed, \TeX\ is in math mode and +working on an mlist; this formula has temporarily interrupted \TeX\ from +being in horizontal mode and building the hlist of a paragraph; and this +paragraph has temporarily interrupted \TeX\ from being in vertical mode +and building the vlist for the next page of a document. Similarly, when a +\.{\\vbox} occurs inside of an \.{\\hbox}, \TeX\ is temporarily +interrupted from working in restricted horizontal mode, and it enters +internal vertical mode. The ``semantic nest'' is a stack that +keeps track of what lists and modes are currently suspended. + +At each level of processing we are in one of six modes: + +\yskip\hang|vmode| stands for vertical mode (the page builder); + +\hang|hmode| stands for horizontal mode (the paragraph builder); + +\hang|mmode| stands for displayed formula mode; + +\hang|-vmode| stands for internal vertical mode (e.g., in a \.{\\vbox}); + +\hang|-hmode| stands for restricted horizontal mode (e.g., in an \.{\\hbox}); + +\hang|-mmode| stands for math formula mode (not displayed). + +\yskip\noindent The mode is temporarily set to zero while processing \.{\\write} +texts. + +Numeric values are assigned to |vmode|, |hmode|, and |mmode| so that +\TeX's ``big semantic switch'' can select the appropriate thing to +do by computing the value |abs(mode)+cur_cmd|, where |mode| is the current +mode and |cur_cmd| is the current command code. + +@d vmode 1 /*vertical mode*/ +@d hmode (vmode+max_command+1) /*horizontal mode*/ +@d mmode (hmode+max_command+1) /*math mode*/ + +@p static void print_mode(int @!m) /*prints the mode represented by |m|*/ +{@+if (m > 0) + switch (m/(max_command+1)) { + case 0: print("vertical");@+break; + case 1: print("horizontal");@+break; + case 2: print("display math"); + } +else if (m==0) print("no"); +else switch ((-m)/(max_command+1)) { + case 0: print("internal vertical");@+break; + case 1: print("restricted horizontal");@+break; + case 2: print("math"); + } +print(" mode"); +} + +@ The state of affairs at any semantic level can be represented by +five values: + +\yskip\hang|mode| is the number representing the semantic mode, as +just explained. + +\yskip\hang|head| is a |pointer| to a list head for the list being built; +|link(head)| therefore points to the first element of the list, or +to |null| if the list is empty. + +\yskip\hang|tail| is a |pointer| to the final node of the list being +built; thus, |tail==head| if and only if the list is empty. + +\yskip\hang|prev_graf| is the number of lines of the current paragraph that +have already been put into the present vertical list. + +\yskip\hang|aux| is an auxiliary |memory_word| that gives further information +that is needed to characterize the situation. + +\yskip\noindent +In vertical mode, |aux| is also known as |prev_depth|; it is the scaled +value representing the depth of the previous box, for use in baseline +calculations, or it is | <= -1000|pt if the next box on the vertical list is to +be exempt from baseline calculations. In horizontal mode, |aux| is also +known as |space_factor| and |clang|; it holds the current space factor used in +spacing calculations, and the current language used for hyphenation. +(The value of |clang| is undefined in restricted horizontal mode.) +In math mode, |aux| is also known as |incompleat_noad|; if +not |null|, it points to a record that represents the numerator of a +generalized fraction for which the denominator is currently being formed +in the current list. + +There is also a sixth quantity, |mode_line|, which correlates +the semantic nest with the user's input; |mode_line| contains the source +line number at which the current level of nesting was entered. The negative +of this line number is the |mode_line| at the level of the +user's output routine. + +A seventh quantity, |eTeX_aux|, is used by the extended features \eTeX. +In vertical modes it is known as |LR_save| and holds the LR stack when a +paragraph is interrupted by a displayed formula. In display math mode +it is known as |LR_box| and holds a pointer to a prototype box for the +display. In math mode it is known as |delim_ptr| and points to the most +recent |left_noad| or |middle_noad| of a |math_left_group|. + +In horizontal mode, the |prev_graf| field is used for initial language data. + +The semantic nest is an array called |nest| that holds the |mode|, |head|, +|tail|, |prev_graf|, |aux|, and |mode_line| values for all semantic levels +below the currently active one. Information about the currently active +level is kept in the global quantities |mode|, |head|, |tail|, |prev_graf|, +|aux|, and |mode_line|, which live in a \PASCAL\ record that is ready to +be pushed onto |nest| if necessary. + +@d ignore_depth -65536000 /*|prev_depth| value that is ignored*/ + +@= +typedef struct { int16_t @!mode_field;@+ + pointer @!head_field, @!tail_field; + pointer @!eTeX_aux_field; + int @!pg_field, @!ml_field;@+ + memory_word @!aux_field; + } list_state_record; + +@ @d mode cur_list.mode_field /*current mode*/ +@d head cur_list.head_field /*header node of current list*/ +@d tail cur_list.tail_field /*final node on current list*/ +@d eTeX_aux cur_list.eTeX_aux_field /*auxiliary data for \eTeX*/ +@d LR_save eTeX_aux /*LR stack when a paragraph is interrupted*/ +@d LR_box eTeX_aux /*prototype box for display*/ +@d delim_ptr eTeX_aux /*most recent left or right noad of a math left group*/ +@d prev_graf cur_list.pg_field /*number of paragraph lines accumulated*/ +@d aux cur_list.aux_field /*auxiliary data about the current list*/ +@d prev_depth aux.sc /*the name of |aux| in vertical mode*/ +@d space_factor aux.hh.lh /*part of |aux| in horizontal mode*/ +@d clang aux.hh.rh /*the other part of |aux| in horizontal mode*/ +@d incompleat_noad aux.i /*the name of |aux| in math mode*/ +@d mode_line cur_list.ml_field /*source file line number at beginning of list*/ + +@= +static list_state_record @!nest[nest_size+1]; +static int @!nest_ptr; /*first unused location of |nest|*/ +static int @!max_nest_stack; /*maximum of |nest_ptr| when pushing*/ +static list_state_record @!cur_list; /*the ``top'' semantic state*/ +static int @!shown_mode; /*most recent mode shown by \.{\\tracingcommands}*/ + +@ Here is a common way to make the current list grow: + +@d tail_append(A) {@+link(tail)=A;tail=link(tail); + } + +@ We will see later that the vertical list at the bottom semantic level is split +into two parts; the ``current page'' runs from |page_head| to |page_tail|, +and the ``contribution list'' runs from |contrib_head| to |tail| of +semantic level zero. The idea is that contributions are first formed in +vertical mode, then ``contributed'' to the current page (during which time +the page-breaking decisions are made). For now, we don't need to know +any more details about the page-building process. + +@= +nest_ptr=0;max_nest_stack=0; +mode=vmode;head=contrib_head;tail=contrib_head; +eTeX_aux=null; +prev_depth=ignore_depth;mode_line=0; +prev_graf=0;shown_mode=0; +@; + +@ When \TeX's work on one level is interrupted, the state is saved by +calling |push_nest|. This routine changes |head| and |tail| so that +a new (empty) list is begun; it does not change |mode| or |aux|. + +@p static void push_nest(void) /*enter a new semantic level, save the old*/ +{@+if (nest_ptr > max_nest_stack) + {@+max_nest_stack=nest_ptr; + if (nest_ptr==nest_size) overflow("semantic nest size", nest_size); +@:TeX capacity exceeded semantic nest size}{\quad semantic nest size@> + } +nest[nest_ptr]=cur_list; /*stack the record*/ +incr(nest_ptr);head=get_avail();tail=head;prev_graf=0;mode_line=line; +eTeX_aux=null; +} + +@ Conversely, when \TeX\ is finished on the current level, the former +state is restored by calling |pop_nest|. This routine will never be +called at the lowest semantic level, nor will it be called unless |head| +is a node that should be returned to free memory. + +@p static void pop_nest(void) /*leave a semantic level, re-enter the old*/ +{@+free_avail(head);decr(nest_ptr);cur_list=nest[nest_ptr]; +} + +@ Here is a procedure that displays what \TeX\ is working on, at all levels. + +@p static void print_totals(void); +static void show_activities(void) +{@+int p; /*index into |nest|*/ +int @!m; /*mode*/ +memory_word @!a; /*auxiliary*/ +pointer @!q, @!r; /*for showing the current page*/ +int @!t; /*ditto*/ +nest[nest_ptr]=cur_list; /*put the top level into the array*/ +print_nl("");print_ln(); +for (p=nest_ptr; p>=0; p--) + {@+m=nest[p].mode_field;a=nest[p].aux_field; + print_nl("### ");print_mode(m); + print(" entered at line ");print_int(abs(nest[p].ml_field)); + if (m==hmode) if (nest[p].pg_field!=040600000) + {@+print(" (language");print_int(nest[p].pg_field%0200000); + print(":hyphenmin");print_int(nest[p].pg_field/020000000); + print_char(',');print_int((nest[p].pg_field/0200000)%0100); + print_char(')'); + } + if (nest[p].ml_field < 0) print(" (\\output routine)"); + if (p==0) + {@+@; + if (link(contrib_head)!=null) + print_nl("### recent contributions:"); + } + show_box(link(nest[p].head_field)); + @; + } +} + +@ @= +switch (abs(m)/(max_command+1)) { +case 0: {@+print_nl("prevdepth "); + if (a.sc <= ignore_depth) print("ignored"); + else print_scaled(a.sc); + if (nest[p].pg_field!=0) + {@+print(", prevgraf "); + print_int(nest[p].pg_field);print(" line"); + if (nest[p].pg_field!=1) print_char('s'); + } + } @+break; +case 1: {@+print_nl("spacefactor ");print_int(a.hh.lh); + if (m > 0) @+if (a.hh.rh > 0) + {@+print(", current language ");print_int(a.hh.rh);@+ + } + } @+break; +case 2: if (a.i!=null) + {@+print("this will begin denominator of:");show_box(a.i);@+ + } +} /*there are no other cases*/ + +@* The table of equivalents. +Now that we have studied the data structures for \TeX's semantic routines, +we ought to consider the data structures used by its syntactic routines. In +other words, our next concern will be +the tables that \TeX\ looks at when it is scanning +what the user has written. + +The biggest and most important such table is called |eqtb|. It holds the +current ``equivalents'' of things; i.e., it explains what things mean +or what their current values are, for all quantities that are subject to +the nesting structure provided by \TeX's grouping mechanism. There are six +parts to |eqtb|: + +\yskip\hangg 1) |eqtb[active_base dotdot(hash_base-1)]| holds the current +equivalents of single-character control sequences. + +\yskip\hangg 2) |eqtb[hash_base dotdot(glue_base-1)]| holds the current +equivalents of multiletter control sequences. + +\yskip\hangg 3) |eqtb[glue_base dotdot(local_base-1)]| holds the current +equivalents of glue parameters like the current baselineskip. + +\yskip\hangg 4) |eqtb[local_base dotdot(int_base-1)]| holds the current +equivalents of local halfword quantities like the current box registers, +the current ``catcodes,'' the current font, and a pointer to the current +paragraph shape. + +\yskip\hangg 5) |eqtb[int_base dotdot(dimen_base-1)]| holds the current +equivalents of fullword integer parameters like the current hyphenation +penalty. + +\yskip\hangg 6) |eqtb[dimen_base dotdot eqtb_size]| holds the current equivalents +of fullword dimension parameters like the current hsize or amount of +hanging indentation. + +\yskip\noindent Note that, for example, the current amount of +baselineskip glue is determined by the setting of a particular location +in region~3 of |eqtb|, while the current meaning of the control sequence +`\.{\\baselineskip}' (which might have been changed by \.{\\def} or +\.{\\let}) appears in region~2. + +@ Each entry in |eqtb| is a |memory_word|. Most of these words are of type +|two_halves|, and subdivided into three fields: + +\yskip\hangg 1) The |eq_level| (a quarterword) is the level of grouping at +which this equivalent was defined. If the level is |level_zero|, the +equivalent has never been defined; |level_one| refers to the outer level +(outside of all groups), and this level is also used for global +definitions that never go away. Higher levels are for equivalents that +will disappear at the end of their group. @^global definitions@> + +\yskip\hangg 2) The |eq_type| (another quarterword) specifies what kind of +entry this is. There are many types, since each \TeX\ primitive like +\.{\\hbox}, \.{\\def}, etc., has its own special code. The list of +command codes above includes all possible settings of the |eq_type| field. + +\yskip\hangg 3) The |equiv| (a halfword) is the current equivalent value. +This may be a font number, a pointer into |mem|, or a variety of other +things. + +@d eq_level_field(A) A.hh.b1 +@d eq_type_field(A) A.hh.b0 +@d equiv_field(A) A.hh.rh +@d eq_level(A) eq_level_field(eqtb[A]) /*level of definition*/ +@d eq_type(A) eq_type_field(eqtb[A]) /*command code for equivalent*/ +@d equiv(A) equiv_field(eqtb[A]) /*equivalent value*/ +@d level_zero min_quarterword /*level for undefined quantities*/ +@d level_one (level_zero+1) /*outermost level for defined quantities*/ + +@ Many locations in |eqtb| have symbolic names. The purpose of the next +paragraphs is to define these names, and to set up the initial values of the +equivalents. + +In the first region we have 256 equivalents for ``active characters'' that +act as control sequences, followed by 256 equivalents for single-character +control sequences. + +Then comes region~2, which corresponds to the hash table that we will +define later. The maximum address in this region is used for a dummy +control sequence that is perpetually undefined. There also are several +locations for control sequences that are perpetually defined +(since they are used in error recovery). + +@d active_base 1 /*beginning of region 1, for active character equivalents*/ +@d single_base (active_base+256) /*equivalents of one-character control sequences*/ +@d null_cs (single_base+256) /*equivalent of \.{\\csname\\endcsname}*/ +@d hash_base (null_cs+1) /*beginning of region 2, for the hash table*/ +@d frozen_control_sequence (hash_base+hash_size) /*for error recovery*/ +@d frozen_protection frozen_control_sequence /*inaccessible but definable*/ +@d frozen_cr (frozen_control_sequence+1) /*permanent `\.{\\cr}'*/ +@d frozen_end_group (frozen_control_sequence+2) /*permanent `\.{\\endgroup}'*/ +@d frozen_right (frozen_control_sequence+3) /*permanent `\.{\\right}'*/ +@d frozen_fi (frozen_control_sequence+4) /*permanent `\.{\\fi}'*/ +@d frozen_end_template (frozen_control_sequence+5) /*permanent `\.{\\endtemplate}'*/ +@d frozen_endv (frozen_control_sequence+6) /*second permanent `\.{\\endtemplate}'*/ +@d frozen_relax (frozen_control_sequence+7) /*permanent `\.{\\relax}'*/ +@d end_write (frozen_control_sequence+8) /*permanent `\.{\\endwrite}'*/ +@d frozen_dont_expand (frozen_control_sequence+9) + /*permanent `\.{\\notexpanded:}'*/ +@d frozen_primitive (frozen_control_sequence+10) + /*permanent `\.{\\primitive:}'*/ +@d frozen_null_font (frozen_control_sequence+11) + /*permanent `\.{\\nullfont}'*/ +@d font_id_base (frozen_null_font-font_base) + /*begins table of 257 permanent font identifiers*/ +@d undefined_control_sequence (frozen_null_font+257) /*dummy location*/ +@d glue_base (undefined_control_sequence+1) /*beginning of region 3*/ + +@= +eq_type(undefined_control_sequence)=undefined_cs; +equiv(undefined_control_sequence)=null; +eq_level(undefined_control_sequence)=level_zero; +for (k=active_base; k<=undefined_control_sequence-1; k++) + eqtb[k]=eqtb[undefined_control_sequence]; + +@ Here is a routine that displays the current meaning of an |eqtb| entry +in region 1 or~2. (Similar routines for the other regions will appear +below.) + +@= +{@+sprint_cs(n);print_char('=');print_cmd_chr(eq_type(n), equiv(n)); +if (eq_type(n) >= call) + {@+print_char(':');show_token_list(link(equiv(n)), null, 32); + } +} + +@ Region 3 of |eqtb| contains the 256 \.{\\skip} registers, as well as the +glue parameters defined here. It is important that the ``muskip'' +parameters have larger numbers than the others. + +@d line_skip_code 0 /*interline glue if |baseline_skip| is infeasible*/ +@d baseline_skip_code 1 /*desired glue between baselines*/ +@d par_skip_code 2 /*extra glue just above a paragraph*/ +@d above_display_skip_code 3 /*extra glue just above displayed math*/ +@d below_display_skip_code 4 /*extra glue just below displayed math*/ +@d above_display_short_skip_code 5 + /*glue above displayed math following short lines*/ +@d below_display_short_skip_code 6 + /*glue below displayed math following short lines*/ +@d left_skip_code 7 /*glue at left of justified lines*/ +@d right_skip_code 8 /*glue at right of justified lines*/ +@d top_skip_code 9 /*glue at top of main pages*/ +@d split_top_skip_code 10 /*glue at top of split pages*/ +@d tab_skip_code 11 /*glue between aligned entries*/ +@d space_skip_code 12 /*glue between words (if not |zero_glue|)*/ +@d xspace_skip_code 13 /*glue after sentences (if not |zero_glue|)*/ +@d par_fill_skip_code 14 /*glue on last line of paragraph*/ +@d thin_mu_skip_code 15 /*thin space in math formula*/ +@d med_mu_skip_code 16 /*medium space in math formula*/ +@d thick_mu_skip_code 17 /*thick space in math formula*/ +@d glue_pars 18 /*total number of glue parameters*/ +@d skip_base (glue_base+glue_pars) /*table of 256 ``skip'' registers*/ +@d mu_skip_base (skip_base+256) /*table of 256 ``muskip'' registers*/ +@d local_base (mu_skip_base+256) /*beginning of region 4*/ +@# +@d skip(A) equiv(skip_base+A) /*|mem| location of glue specification*/ +@d mu_skip(A) equiv(mu_skip_base+A) /*|mem| location of math glue spec*/ +@d glue_par(A) equiv(glue_base+A) /*|mem| location of glue specification*/ +@d line_skip glue_par(line_skip_code) +@d baseline_skip glue_par(baseline_skip_code) +@d par_skip glue_par(par_skip_code) +@d above_display_skip glue_par(above_display_skip_code) +@d below_display_skip glue_par(below_display_skip_code) +@d above_display_short_skip glue_par(above_display_short_skip_code) +@d below_display_short_skip glue_par(below_display_short_skip_code) +@d left_skip glue_par(left_skip_code) +@d right_skip glue_par(right_skip_code) +@d top_skip glue_par(top_skip_code) +@d split_top_skip glue_par(split_top_skip_code) +@d tab_skip glue_par(tab_skip_code) +@d space_skip glue_par(space_skip_code) +@d xspace_skip glue_par(xspace_skip_code) +@d par_fill_skip glue_par(par_fill_skip_code) +@d thin_mu_skip glue_par(thin_mu_skip_code) +@d med_mu_skip glue_par(med_mu_skip_code) +@d thick_mu_skip glue_par(thick_mu_skip_code) + +@=glue_par(n) + +@ Sometimes we need to convert \TeX's internal code numbers into symbolic +form. The |print_skip_param| routine gives the symbolic name of a glue +parameter. + +@= +static void print_skip_param(int @!n) +{@+switch (n) { +case line_skip_code: print_esc("lineskip");@+break; +case baseline_skip_code: print_esc("baselineskip");@+break; +case par_skip_code: print_esc("parskip");@+break; +case above_display_skip_code: print_esc("abovedisplayskip");@+break; +case below_display_skip_code: print_esc("belowdisplayskip");@+break; +case above_display_short_skip_code: print_esc("abovedisplayshortskip");@+break; +case below_display_short_skip_code: print_esc("belowdisplayshortskip");@+break; +case left_skip_code: print_esc("leftskip");@+break; +case right_skip_code: print_esc("rightskip");@+break; +case top_skip_code: print_esc("topskip");@+break; +case split_top_skip_code: print_esc("splittopskip");@+break; +case tab_skip_code: print_esc("tabskip");@+break; +case space_skip_code: print_esc("spaceskip");@+break; +case xspace_skip_code: print_esc("xspaceskip");@+break; +case par_fill_skip_code: print_esc("parfillskip");@+break; +case thin_mu_skip_code: print_esc("thinmuskip");@+break; +case med_mu_skip_code: print_esc("medmuskip");@+break; +case thick_mu_skip_code: print_esc("thickmuskip");@+break; +default:print("[unknown glue parameter!]"); +} +} + +@ The symbolic names for glue parameters are put into \TeX's hash table +by using the routine called |primitive|, defined below. Let us enter them +now, so that we don't have to list all those parameter names anywhere else. + +@= +primitive("lineskip", assign_glue, glue_base+line_skip_code);@/ +@!@:line\_skip\_}{\.{\\lineskip} primitive@> +primitive("baselineskip", assign_glue, glue_base+baseline_skip_code);@/ +@!@:baseline\_skip\_}{\.{\\baselineskip} primitive@> +primitive("parskip", assign_glue, glue_base+par_skip_code);@/ +@!@:par\_skip\_}{\.{\\parskip} primitive@> +primitive("abovedisplayskip", assign_glue, glue_base+above_display_skip_code);@/ +@!@:above\_display\_skip\_}{\.{\\abovedisplayskip} primitive@> +primitive("belowdisplayskip", assign_glue, glue_base+below_display_skip_code);@/ +@!@:below\_display\_skip\_}{\.{\\belowdisplayskip} primitive@> +primitive("abovedisplayshortskip", + assign_glue, glue_base+above_display_short_skip_code);@/ +@!@:above\_display\_short\_skip\_}{\.{\\abovedisplayshortskip} primitive@> +primitive("belowdisplayshortskip", + assign_glue, glue_base+below_display_short_skip_code);@/ +@!@:below\_display\_short\_skip\_}{\.{\\belowdisplayshortskip} primitive@> +primitive("leftskip", assign_glue, glue_base+left_skip_code);@/ +@!@:left\_skip\_}{\.{\\leftskip} primitive@> +primitive("rightskip", assign_glue, glue_base+right_skip_code);@/ +@!@:right\_skip\_}{\.{\\rightskip} primitive@> +primitive("topskip", assign_glue, glue_base+top_skip_code);@/ +@!@:top\_skip\_}{\.{\\topskip} primitive@> +primitive("splittopskip", assign_glue, glue_base+split_top_skip_code);@/ +@!@:split\_top\_skip\_}{\.{\\splittopskip} primitive@> +primitive("tabskip", assign_glue, glue_base+tab_skip_code);@/ +@!@:tab\_skip\_}{\.{\\tabskip} primitive@> +primitive("spaceskip", assign_glue, glue_base+space_skip_code);@/ +@!@:space\_skip\_}{\.{\\spaceskip} primitive@> +primitive("xspaceskip", assign_glue, glue_base+xspace_skip_code);@/ +@!@:xspace\_skip\_}{\.{\\xspaceskip} primitive@> +primitive("parfillskip", assign_glue, glue_base+par_fill_skip_code);@/ +@!@:par\_fill\_skip\_}{\.{\\parfillskip} primitive@> +primitive("thinmuskip", assign_mu_glue, glue_base+thin_mu_skip_code);@/ +@!@:thin\_mu\_skip\_}{\.{\\thinmuskip} primitive@> +primitive("medmuskip", assign_mu_glue, glue_base+med_mu_skip_code);@/ +@!@:med\_mu\_skip\_}{\.{\\medmuskip} primitive@> +primitive("thickmuskip", assign_mu_glue, glue_base+thick_mu_skip_code);@/ +@!@:thick\_mu\_skip\_}{\.{\\thickmuskip} primitive@> + +@ @= +case assign_glue: case assign_mu_glue: if (chr_code < skip_base) + print_skip_param(chr_code-glue_base); + else if (chr_code < mu_skip_base) + {@+print_esc("skip");print_int(chr_code-skip_base); + } + else{@+print_esc("muskip");print_int(chr_code-mu_skip_base); + } @+break; + +@ All glue parameters and registers are initially `\.{0pt plus0pt minus0pt}'. + +@= +equiv(glue_base)=zero_glue;eq_level(glue_base)=level_one; +eq_type(glue_base)=glue_ref; +for (k=glue_base+1; k<=local_base-1; k++) eqtb[k]=eqtb[glue_base]; +glue_ref_count(zero_glue)=glue_ref_count(zero_glue)+local_base-glue_base; + +@ @= +if (n < skip_base) + {@+print_skip_param(n-glue_base);print_char('='); + if (n < glue_base+thin_mu_skip_code) print_spec(equiv(n),"pt"); + else print_spec(equiv(n),"mu"); + } +else if (n < mu_skip_base) + {@+print_esc("skip");print_int(n-skip_base);print_char('='); + print_spec(equiv(n),"pt"); + } +else{@+print_esc("muskip");print_int(n-mu_skip_base);print_char('='); + print_spec(equiv(n),"mu"); + } + +@ Region 4 of |eqtb| contains the local quantities defined here. The +bulk of this region is taken up by five tables that are indexed by eight-bit +characters; these tables are important to both the syntactic and semantic +portions of \TeX. There are also a bunch of special things like font and +token parameters, as well as the tables of \.{\\toks} and \.{\\box} +registers. + +@d par_shape_loc local_base /*specifies paragraph shape*/ +@d output_routine_loc (local_base+1) /*points to token list for \.{\\output}*/ +@d every_par_loc (local_base+2) /*points to token list for \.{\\everypar}*/ +@d every_math_loc (local_base+3) /*points to token list for \.{\\everymath}*/ +@d every_display_loc (local_base+4) /*points to token list for \.{\\everydisplay}*/ +@d every_hbox_loc (local_base+5) /*points to token list for \.{\\everyhbox}*/ +@d every_vbox_loc (local_base+6) /*points to token list for \.{\\everyvbox}*/ +@d every_job_loc (local_base+7) /*points to token list for \.{\\everyjob}*/ +@d every_cr_loc (local_base+8) /*points to token list for \.{\\everycr}*/ +@d err_help_loc (local_base+9) /*points to token list for \.{\\errhelp}*/ +@d tex_toks (local_base+10) /*end of \TeX's token list parameters*/ +@# +@d etex_toks_base pdf_toks /*base for \eTeX's token list parameters*/ +@d every_eof_loc etex_toks_base /*points to token list for \.{\\everyeof}*/ +@d etex_toks (etex_toks_base+1) /*end of \eTeX's token list parameters*/ +@# +@d toks_base etex_toks /*table of 256 token list registers*/ +@# +@d etex_pen_base (toks_base+256) /*start of table of \eTeX's penalties*/ +@d inter_line_penalties_loc etex_pen_base /*additional penalties between lines*/ +@d club_penalties_loc (etex_pen_base+1) /*penalties for creating club lines*/ +@d widow_penalties_loc (etex_pen_base+2) /*penalties for creating widow lines*/ +@d display_widow_penalties_loc (etex_pen_base+3) /*ditto, just before a display*/ +@d etex_pens (etex_pen_base+4) /*end of table of \eTeX's penalties*/ +@# +@d box_base etex_pens /*table of 256 box registers*/ +@d cur_font_loc (box_base+256) /*internal font number outside math mode*/ +@d math_font_base (cur_font_loc+1) /*table of 48 math font numbers*/ +@d cat_code_base (math_font_base+48) + /*table of 256 command codes (the ``catcodes'')*/ +@d lc_code_base (cat_code_base+256) /*table of 256 lowercase mappings*/ +@d uc_code_base (lc_code_base+256) /*table of 256 uppercase mappings*/ +@d sf_code_base (uc_code_base+256) /*table of 256 spacefactor mappings*/ +@d math_code_base (sf_code_base+256) /*table of 256 math mode mappings*/ +@d int_base (math_code_base+256) /*beginning of region 5*/ +@# +@d par_shape_ptr equiv(par_shape_loc) +@d output_routine equiv(output_routine_loc) +@d every_par equiv(every_par_loc) +@d every_math equiv(every_math_loc) +@d every_display equiv(every_display_loc) +@d every_hbox equiv(every_hbox_loc) +@d every_vbox equiv(every_vbox_loc) +@d every_job equiv(every_job_loc) +@d every_cr equiv(every_cr_loc) +@d err_help equiv(err_help_loc) +@d toks(X) equiv(toks_base+X) +@d box(A) equiv(box_base+A) +@d cur_font equiv(cur_font_loc) +@d fam_fnt(A) equiv(math_font_base+A) +@d cat_code(A) equiv(cat_code_base+A) +@d lc_code(A) equiv(lc_code_base+A) +@d uc_code(A) equiv(uc_code_base+A) +@d sf_code(A) equiv(sf_code_base+A) +@d math_code(A) equiv(math_code_base+A) + /*Note: |math_code(c)| is the true math code plus |min_halfword|*/ + +@= +primitive("output", assign_toks, output_routine_loc); +@!@:output\_}{\.{\\output} primitive@> +primitive("everypar", assign_toks, every_par_loc); +@!@:every\_par\_}{\.{\\everypar} primitive@> +primitive("everymath", assign_toks, every_math_loc); +@!@:every\_math\_}{\.{\\everymath} primitive@> +primitive("everydisplay", assign_toks, every_display_loc); +@!@:every\_display\_}{\.{\\everydisplay} primitive@> +primitive("everyhbox", assign_toks, every_hbox_loc); +@!@:every\_hbox\_}{\.{\\everyhbox} primitive@> +primitive("everyvbox", assign_toks, every_vbox_loc); +@!@:every\_vbox\_}{\.{\\everyvbox} primitive@> +primitive("everyjob", assign_toks, every_job_loc); +@!@:every\_job\_}{\.{\\everyjob} primitive@> +primitive("everycr", assign_toks, every_cr_loc); +@!@:every\_cr\_}{\.{\\everycr} primitive@> +primitive("errhelp", assign_toks, err_help_loc); +@!@:err\_help\_}{\.{\\errhelp} primitive@> + +@ @= +case assign_toks: if (chr_code >= toks_base) + {@+print_esc("toks");print_int(chr_code-toks_base); + } +else switch (chr_code) { + case output_routine_loc: print_esc("output");@+break; + case every_par_loc: print_esc("everypar");@+break; + case every_math_loc: print_esc("everymath");@+break; + case every_display_loc: print_esc("everydisplay");@+break; + case every_hbox_loc: print_esc("everyhbox");@+break; + case every_vbox_loc: print_esc("everyvbox");@+break; + case every_job_loc: print_esc("everyjob");@+break; + case every_cr_loc: print_esc("everycr");@+break; + @/@@/ + default:print_esc("errhelp"); + } @+break; + +@ We initialize most things to null or undefined values. An undefined font +is represented by the internal code |font_base|. + +However, the character code tables are given initial values based on the +conventional interpretation of ASCII code. These initial values should +not be changed when \TeX\ is adapted for use with non-English languages; +all changes to the initialization conventions should be made in format +packages, not in \TeX\ itself, so that global interchange of formats is +possible. + +@d null_font font_base +@d var_code 070000 /*math code meaning ``use the current family''*/ + +@= +par_shape_ptr=null;eq_type(par_shape_loc)=shape_ref; +eq_level(par_shape_loc)=level_one;@/ +for (k=etex_pen_base; k<=etex_pens-1; k++) + eqtb[k]=eqtb[par_shape_loc]; +for (k=output_routine_loc; k<=toks_base+255; k++) + eqtb[k]=eqtb[undefined_control_sequence]; +box(0)=null;eq_type(box_base)=box_ref;eq_level(box_base)=level_one; +for (k=box_base+1; k<=box_base+255; k++) eqtb[k]=eqtb[box_base]; +cur_font=null_font;eq_type(cur_font_loc)=data; +eq_level(cur_font_loc)=level_one;@/ +for (k=math_font_base; k<=math_font_base+47; k++) eqtb[k]=eqtb[cur_font_loc]; +equiv(cat_code_base)=0;eq_type(cat_code_base)=data; +eq_level(cat_code_base)=level_one;@/ +for (k=cat_code_base+1; k<=int_base-1; k++) eqtb[k]=eqtb[cat_code_base]; +for (k=0; k<=255; k++) + {@+cat_code(k)=other_char;math_code(k)=hi(k);sf_code(k)=1000; + } +cat_code(carriage_return)=car_ret;cat_code(' ')=spacer; +cat_code('\\')=escape;cat_code('%')=comment; +cat_code(invalid_code)=invalid_char;cat_code(null_code)=ignore; +for (k='0'; k<='9'; k++) math_code(k)=hi(k+var_code); +for (k='A'; k<='Z'; k++) + {@+cat_code(k)=letter;cat_code(k+'a'-'A')=letter;@/ + math_code(k)=hi(k+var_code+0x100); + math_code(k+'a'-'A')=hi(k+'a'-'A'+var_code+0x100);@/ + lc_code(k)=k+'a'-'A';lc_code(k+'a'-'A')=k+'a'-'A';@/ + uc_code(k)=k;uc_code(k+'a'-'A')=k;@/ + sf_code(k)=999; + } + +@ @= +if ((n==par_shape_loc)||((n >= etex_pen_base)&&(n < etex_pens))) + {@+print_cmd_chr(set_shape, n);print_char('='); + if (equiv(n)==null) print_char('0'); + else if (n > par_shape_loc) + {@+print_int(penalty(equiv(n)));print_char(' '); + print_int(penalty(equiv(n)+1)); + if (penalty(equiv(n)) > 1) print_esc("ETC."); + } + else print_int(info(par_shape_ptr)); + } +else if (n < toks_base) + {@+print_cmd_chr(assign_toks, n);print_char('='); + if (equiv(n)!=null) show_token_list(link(equiv(n)), null, 32); + } +else if (n < box_base) + {@+print_esc("toks");print_int(n-toks_base);print_char('='); + if (equiv(n)!=null) show_token_list(link(equiv(n)), null, 32); + } +else if (n < cur_font_loc) + {@+print_esc("box");print_int(n-box_base);print_char('='); + if (equiv(n)==null) print("void"); + else{@+depth_threshold=0;breadth_max=1;show_node_list(equiv(n)); + } + } +else if (n < cat_code_base) @@; +else@@; + +@ @= +{@+if (n==cur_font_loc) print("current font"); +else if (n < math_font_base+16) + {@+print_esc("textfont");print_int(n-math_font_base); + } +else if (n < math_font_base+32) + {@+print_esc("scriptfont");print_int(n-math_font_base-16); + } +else{@+print_esc("scriptscriptfont");print_int(n-math_font_base-32); + } +print_char('=');@/ +printn_esc(hash[font_id_base+equiv(n)].rh); + /*that's |font_id_text(equiv(n))|*/ +} + +@ @= +if (n < math_code_base) + {@+if (n < lc_code_base) + {@+print_esc("catcode");print_int(n-cat_code_base); + } + else if (n < uc_code_base) + {@+print_esc("lccode");print_int(n-lc_code_base); + } + else if (n < sf_code_base) + {@+print_esc("uccode");print_int(n-uc_code_base); + } + else{@+print_esc("sfcode");print_int(n-sf_code_base); + } + print_char('=');print_int(equiv(n)); + } +else{@+print_esc("mathcode");print_int(n-math_code_base); + print_char('=');print_int(ho(equiv(n))); + } + +@ Region 5 of |eqtb| contains the integer parameters and registers defined +here, as well as the |del_code| table. The latter table differs from the +|cat_code dotdot math_code| tables that precede it, since delimiter codes are +fullword integers while the other kinds of codes occupy at most a +halfword. This is what makes region~5 different from region~4. We will +store the |eq_level| information in an auxiliary array of quarterwords +that will be defined later. + +@d pretolerance_code 0 /*badness tolerance before hyphenation*/ +@d tolerance_code 1 /*badness tolerance after hyphenation*/ +@d line_penalty_code 2 /*added to the badness of every line*/ +@d hyphen_penalty_code 3 /*penalty for break after discretionary hyphen*/ +@d ex_hyphen_penalty_code 4 /*penalty for break after explicit hyphen*/ +@d club_penalty_code 5 /*penalty for creating a club line*/ +@d widow_penalty_code 6 /*penalty for creating a widow line*/ +@d display_widow_penalty_code 7 /*ditto, just before a display*/ +@d broken_penalty_code 8 /*penalty for breaking a page at a broken line*/ +@d bin_op_penalty_code 9 /*penalty for breaking after a binary operation*/ +@d rel_penalty_code 10 /*penalty for breaking after a relation*/ +@d pre_display_penalty_code 11 + /*penalty for breaking just before a displayed formula*/ +@d post_display_penalty_code 12 + /*penalty for breaking just after a displayed formula*/ +@d inter_line_penalty_code 13 /*additional penalty between lines*/ +@d double_hyphen_demerits_code 14 /*demerits for double hyphen break*/ +@d final_hyphen_demerits_code 15 /*demerits for final hyphen break*/ +@d adj_demerits_code 16 /*demerits for adjacent incompatible lines*/ +@d mag_code 17 /*magnification ratio*/ +@d delimiter_factor_code 18 /*ratio for variable-size delimiters*/ +@d looseness_code 19 /*change in number of lines for a paragraph*/ +@d time_code 20 /*current time of day*/ +@d day_code 21 /*current day of the month*/ +@d month_code 22 /*current month of the year*/ +@d year_code 23 /*current year of our Lord*/ +@d show_box_breadth_code 24 /*nodes per level in |show_box|*/ +@d show_box_depth_code 25 /*maximum level in |show_box|*/ +@d hbadness_code 26 /*hboxes exceeding this badness will be shown by |hpack|*/ +@d vbadness_code 27 /*vboxes exceeding this badness will be shown by |vpack|*/ +@d pausing_code 28 /*pause after each line is read from a file*/ +@d tracing_online_code 29 /*show diagnostic output on terminal*/ +@d tracing_macros_code 30 /*show macros as they are being expanded*/ +@d tracing_stats_code 31 /*show memory usage if \TeX\ knows it*/ +@d tracing_paragraphs_code 32 /*show line-break calculations*/ +@d tracing_pages_code 33 /*show page-break calculations*/ +@d tracing_output_code 34 /*show boxes when they are shipped out*/ +@d tracing_lost_chars_code 35 /*show characters that aren't in the font*/ +@d tracing_commands_code 36 /*show command codes at |big_switch|*/ +@d tracing_restores_code 37 /*show equivalents when they are restored*/ +@d uc_hyph_code 38 /*hyphenate words beginning with a capital letter*/ +@d output_penalty_code 39 /*penalty found at current page break*/ +@d max_dead_cycles_code 40 /*bound on consecutive dead cycles of output*/ +@d hang_after_code 41 /*hanging indentation changes after this many lines*/ +@d floating_penalty_code 42 /*penalty for insertions held over after a split*/ +@d global_defs_code 43 /*override \.{\\global} specifications*/ +@d cur_fam_code 44 /*current family*/ +@d escape_char_code 45 /*escape character for token output*/ +@d default_hyphen_char_code 46 /*value of \.{\\hyphenchar} when a font is loaded*/ +@d default_skew_char_code 47 /*value of \.{\\skewchar} when a font is loaded*/ +@d end_line_char_code 48 /*character placed at the right end of the buffer*/ +@d new_line_char_code 49 /*character that prints as |print_ln|*/ +@d language_code 50 /*current hyphenation table*/ +@d left_hyphen_min_code 51 /*minimum left hyphenation fragment size*/ +@d right_hyphen_min_code 52 /*minimum right hyphenation fragment size*/ +@d holding_inserts_code 53 /*do not remove insertion nodes from \.{\\box255}*/ +@d error_context_lines_code 54 /*maximum intermediate line pairs shown*/ +@d tex_int_pars 55 /*total number of \TeX's integer parameters*/ +@# +@d etex_int_base pdf_int_pars /*base for \eTeX's integer parameters*/ +@d tracing_assigns_code etex_int_base /*show assignments*/ +@d tracing_groups_code (etex_int_base+1) /*show save/restore groups*/ +@d tracing_ifs_code (etex_int_base+2) /*show conditionals*/ +@d tracing_scan_tokens_code (etex_int_base+3) /*show pseudo file open and close*/ +@d tracing_nesting_code (etex_int_base+4) /*show incomplete groups and ifs within files*/ +@d saving_vdiscards_code (etex_int_base+5) /*save items discarded from vlists*/ +@d saving_hyph_codes_code (etex_int_base+6) /*save hyphenation codes for languages*/ +@d expand_depth_code (etex_int_base+7) /*maximum depth for expansion---\eTeX*/ +@d eTeX_state_code (etex_int_base+8) /*\eTeX\ state variables*/ +@d etex_int_pars (eTeX_state_code+eTeX_states) /*total number of \eTeX's integer parameters*/ +@# +@d int_pars etex_int_pars /*total number of integer parameters*/ +@d count_base (int_base+int_pars) /*256 user \.{\\count} registers*/ +@d del_code_base (count_base+256) /*256 delimiter code mappings*/ +@d dimen_base (del_code_base+256) /*beginning of region 6*/ +@# +@d del_code(A) eqtb[del_code_base+A].i +@d count(A) eqtb[count_base+A].i +@d int_par(A) eqtb[int_base+A].i /*an integer parameter*/ +@d pretolerance int_par(pretolerance_code) +@d tolerance int_par(tolerance_code) +@d line_penalty int_par(line_penalty_code) +@d hyphen_penalty int_par(hyphen_penalty_code) +@d ex_hyphen_penalty int_par(ex_hyphen_penalty_code) +@d club_penalty int_par(club_penalty_code) +@d widow_penalty int_par(widow_penalty_code) +@d display_widow_penalty int_par(display_widow_penalty_code) +@d broken_penalty int_par(broken_penalty_code) +@d bin_op_penalty int_par(bin_op_penalty_code) +@d rel_penalty int_par(rel_penalty_code) +@d pre_display_penalty int_par(pre_display_penalty_code) +@d post_display_penalty int_par(post_display_penalty_code) +@d inter_line_penalty int_par(inter_line_penalty_code) +@d double_hyphen_demerits int_par(double_hyphen_demerits_code) +@d final_hyphen_demerits int_par(final_hyphen_demerits_code) +@d adj_demerits int_par(adj_demerits_code) +@d mag int_par(mag_code) +@d delimiter_factor int_par(delimiter_factor_code) +@d looseness int_par(looseness_code) +@d time int_par(time_code) +@d day int_par(day_code) +@d month int_par(month_code) +@d year int_par(year_code) +@d show_box_breadth int_par(show_box_breadth_code) +@d show_box_depth int_par(show_box_depth_code) +@d hbadness int_par(hbadness_code) +@d vbadness int_par(vbadness_code) +@d pausing int_par(pausing_code) +@d tracing_online int_par(tracing_online_code) +@d tracing_macros int_par(tracing_macros_code) +@d tracing_stats int_par(tracing_stats_code) +@d tracing_paragraphs int_par(tracing_paragraphs_code) +@d tracing_pages int_par(tracing_pages_code) +@d tracing_output int_par(tracing_output_code) +@d tracing_lost_chars int_par(tracing_lost_chars_code) +@d tracing_commands int_par(tracing_commands_code) +@d tracing_restores int_par(tracing_restores_code) +@d uc_hyph int_par(uc_hyph_code) +@d output_penalty int_par(output_penalty_code) +@d max_dead_cycles int_par(max_dead_cycles_code) +@d hang_after int_par(hang_after_code) +@d floating_penalty int_par(floating_penalty_code) +@d global_defs int_par(global_defs_code) +@d cur_fam int_par(cur_fam_code) +@d escape_char int_par(escape_char_code) +@d default_hyphen_char int_par(default_hyphen_char_code) +@d default_skew_char int_par(default_skew_char_code) +@d end_line_char int_par(end_line_char_code) +@d new_line_char int_par(new_line_char_code) +@d language int_par(language_code) +@d left_hyphen_min int_par(left_hyphen_min_code) +@d right_hyphen_min int_par(right_hyphen_min_code) +@d holding_inserts int_par(holding_inserts_code) +@d error_context_lines int_par(error_context_lines_code) +@# +@d tracing_assigns int_par(tracing_assigns_code) +@d tracing_groups int_par(tracing_groups_code) +@d tracing_ifs int_par(tracing_ifs_code) +@d tracing_scan_tokens int_par(tracing_scan_tokens_code) +@d tracing_nesting int_par(tracing_nesting_code) +@d saving_vdiscards int_par(saving_vdiscards_code) +@d saving_hyph_codes int_par(saving_hyph_codes_code) +@d expand_depth int_par(expand_depth_code) + +@= +depth_threshold=show_box_depth; +breadth_max=show_box_breadth + +@ We can print the symbolic name of an integer parameter as follows. + +@p static void print_param(int @!n) +{@+switch (n) { +case pretolerance_code: print_esc("pretolerance");@+break; +case tolerance_code: print_esc("tolerance");@+break; +case line_penalty_code: print_esc("linepenalty");@+break; +case hyphen_penalty_code: print_esc("hyphenpenalty");@+break; +case ex_hyphen_penalty_code: print_esc("exhyphenpenalty");@+break; +case club_penalty_code: print_esc("clubpenalty");@+break; +case widow_penalty_code: print_esc("widowpenalty");@+break; +case display_widow_penalty_code: print_esc("displaywidowpenalty");@+break; +case broken_penalty_code: print_esc("brokenpenalty");@+break; +case bin_op_penalty_code: print_esc("binoppenalty");@+break; +case rel_penalty_code: print_esc("relpenalty");@+break; +case pre_display_penalty_code: print_esc("predisplaypenalty");@+break; +case post_display_penalty_code: print_esc("postdisplaypenalty");@+break; +case inter_line_penalty_code: print_esc("interlinepenalty");@+break; +case double_hyphen_demerits_code: print_esc("doublehyphendemerits");@+break; +case final_hyphen_demerits_code: print_esc("finalhyphendemerits");@+break; +case adj_demerits_code: print_esc("adjdemerits");@+break; +case mag_code: print_esc("mag");@+break; +case delimiter_factor_code: print_esc("delimiterfactor");@+break; +case looseness_code: print_esc("looseness");@+break; +case time_code: print_esc("time");@+break; +case day_code: print_esc("day");@+break; +case month_code: print_esc("month");@+break; +case year_code: print_esc("year");@+break; +case show_box_breadth_code: print_esc("showboxbreadth");@+break; +case show_box_depth_code: print_esc("showboxdepth");@+break; +case hbadness_code: print_esc("hbadness");@+break; +case vbadness_code: print_esc("vbadness");@+break; +case pausing_code: print_esc("pausing");@+break; +case tracing_online_code: print_esc("tracingonline");@+break; +case tracing_macros_code: print_esc("tracingmacros");@+break; +case tracing_stats_code: print_esc("tracingstats");@+break; +case tracing_paragraphs_code: print_esc("tracingparagraphs");@+break; +case tracing_pages_code: print_esc("tracingpages");@+break; +case tracing_output_code: print_esc("tracingoutput");@+break; +case tracing_lost_chars_code: print_esc("tracinglostchars");@+break; +case tracing_commands_code: print_esc("tracingcommands");@+break; +case tracing_restores_code: print_esc("tracingrestores");@+break; +case uc_hyph_code: print_esc("uchyph");@+break; +case output_penalty_code: print_esc("outputpenalty");@+break; +case max_dead_cycles_code: print_esc("maxdeadcycles");@+break; +case hang_after_code: print_esc("hangafter");@+break; +case floating_penalty_code: print_esc("floatingpenalty");@+break; +case global_defs_code: print_esc("globaldefs");@+break; +case cur_fam_code: print_esc("fam");@+break; +case escape_char_code: print_esc("escapechar");@+break; +case default_hyphen_char_code: print_esc("defaulthyphenchar");@+break; +case default_skew_char_code: print_esc("defaultskewchar");@+break; +case end_line_char_code: print_esc("endlinechar");@+break; +case new_line_char_code: print_esc("newlinechar");@+break; +case language_code: print_esc("language");@+break; +case left_hyphen_min_code: print_esc("lefthyphenmin");@+break; +case right_hyphen_min_code: print_esc("righthyphenmin");@+break; +case holding_inserts_code: print_esc("holdinginserts");@+break; +case error_context_lines_code: print_esc("errorcontextlines");@+break; +@/@@/ +default:print("[unknown integer parameter!]"); +} +} + +@ The integer parameter names must be entered into the hash table. + +@= +primitive("pretolerance", assign_int, int_base+pretolerance_code);@/ +@!@:pretolerance\_}{\.{\\pretolerance} primitive@> +primitive("tolerance", assign_int, int_base+tolerance_code);@/ +@!@:tolerance\_}{\.{\\tolerance} primitive@> +primitive("linepenalty", assign_int, int_base+line_penalty_code);@/ +@!@:line\_penalty\_}{\.{\\linepenalty} primitive@> +primitive("hyphenpenalty", assign_int, int_base+hyphen_penalty_code);@/ +@!@:hyphen\_penalty\_}{\.{\\hyphenpenalty} primitive@> +primitive("exhyphenpenalty", assign_int, int_base+ex_hyphen_penalty_code);@/ +@!@:ex\_hyphen\_penalty\_}{\.{\\exhyphenpenalty} primitive@> +primitive("clubpenalty", assign_int, int_base+club_penalty_code);@/ +@!@:club\_penalty\_}{\.{\\clubpenalty} primitive@> +primitive("widowpenalty", assign_int, int_base+widow_penalty_code);@/ +@!@:widow\_penalty\_}{\.{\\widowpenalty} primitive@> +primitive("displaywidowpenalty", + assign_int, int_base+display_widow_penalty_code);@/ +@!@:display\_widow\_penalty\_}{\.{\\displaywidowpenalty} primitive@> +primitive("brokenpenalty", assign_int, int_base+broken_penalty_code);@/ +@!@:broken\_penalty\_}{\.{\\brokenpenalty} primitive@> +primitive("binoppenalty", assign_int, int_base+bin_op_penalty_code);@/ +@!@:bin\_op\_penalty\_}{\.{\\binoppenalty} primitive@> +primitive("relpenalty", assign_int, int_base+rel_penalty_code);@/ +@!@:rel\_penalty\_}{\.{\\relpenalty} primitive@> +primitive("predisplaypenalty", assign_int, int_base+pre_display_penalty_code);@/ +@!@:pre\_display\_penalty\_}{\.{\\predisplaypenalty} primitive@> +primitive("postdisplaypenalty", assign_int, int_base+post_display_penalty_code);@/ +@!@:post\_display\_penalty\_}{\.{\\postdisplaypenalty} primitive@> +primitive("interlinepenalty", assign_int, int_base+inter_line_penalty_code);@/ +@!@:inter\_line\_penalty\_}{\.{\\interlinepenalty} primitive@> +primitive("doublehyphendemerits", + assign_int, int_base+double_hyphen_demerits_code);@/ +@!@:double\_hyphen\_demerits\_}{\.{\\doublehyphendemerits} primitive@> +primitive("finalhyphendemerits", + assign_int, int_base+final_hyphen_demerits_code);@/ +@!@:final\_hyphen\_demerits\_}{\.{\\finalhyphendemerits} primitive@> +primitive("adjdemerits", assign_int, int_base+adj_demerits_code);@/ +@!@:adj\_demerits\_}{\.{\\adjdemerits} primitive@> +primitive("mag", assign_int, int_base+mag_code);@/ +@!@:mag\_}{\.{\\mag} primitive@> +primitive("delimiterfactor", assign_int, int_base+delimiter_factor_code);@/ +@!@:delimiter\_factor\_}{\.{\\delimiterfactor} primitive@> +primitive("looseness", assign_int, int_base+looseness_code);@/ +@!@:looseness\_}{\.{\\looseness} primitive@> +primitive("time", assign_int, int_base+time_code);@/ +@!@:time\_}{\.{\\time} primitive@> +primitive("day", assign_int, int_base+day_code);@/ +@!@:day\_}{\.{\\day} primitive@> +primitive("month", assign_int, int_base+month_code);@/ +@!@:month\_}{\.{\\month} primitive@> +primitive("year", assign_int, int_base+year_code);@/ +@!@:year\_}{\.{\\year} primitive@> +primitive("showboxbreadth", assign_int, int_base+show_box_breadth_code);@/ +@!@:show\_box\_breadth\_}{\.{\\showboxbreadth} primitive@> +primitive("showboxdepth", assign_int, int_base+show_box_depth_code);@/ +@!@:show\_box\_depth\_}{\.{\\showboxdepth} primitive@> +primitive("hbadness", assign_int, int_base+hbadness_code);@/ +@!@:hbadness\_}{\.{\\hbadness} primitive@> +primitive("vbadness", assign_int, int_base+vbadness_code);@/ +@!@:vbadness\_}{\.{\\vbadness} primitive@> +primitive("pausing", assign_int, int_base+pausing_code);@/ +@!@:pausing\_}{\.{\\pausing} primitive@> +primitive("tracingonline", assign_int, int_base+tracing_online_code);@/ +@!@:tracing\_online\_}{\.{\\tracingonline} primitive@> +primitive("tracingmacros", assign_int, int_base+tracing_macros_code);@/ +@!@:tracing\_macros\_}{\.{\\tracingmacros} primitive@> +primitive("tracingstats", assign_int, int_base+tracing_stats_code);@/ +@!@:tracing\_stats\_}{\.{\\tracingstats} primitive@> +primitive("tracingparagraphs", assign_int, int_base+tracing_paragraphs_code);@/ +@!@:tracing\_paragraphs\_}{\.{\\tracingparagraphs} primitive@> +primitive("tracingpages", assign_int, int_base+tracing_pages_code);@/ +@!@:tracing\_pages\_}{\.{\\tracingpages} primitive@> +primitive("tracingoutput", assign_int, int_base+tracing_output_code);@/ +@!@:tracing\_output\_}{\.{\\tracingoutput} primitive@> +primitive("tracinglostchars", assign_int, int_base+tracing_lost_chars_code);@/ +@!@:tracing\_lost\_chars\_}{\.{\\tracinglostchars} primitive@> +primitive("tracingcommands", assign_int, int_base+tracing_commands_code);@/ +@!@:tracing\_commands\_}{\.{\\tracingcommands} primitive@> +primitive("tracingrestores", assign_int, int_base+tracing_restores_code);@/ +@!@:tracing\_restores\_}{\.{\\tracingrestores} primitive@> +primitive("uchyph", assign_int, int_base+uc_hyph_code);@/ +@!@:uc\_hyph\_}{\.{\\uchyph} primitive@> +primitive("outputpenalty", assign_int, int_base+output_penalty_code);@/ +@!@:output\_penalty\_}{\.{\\outputpenalty} primitive@> +primitive("maxdeadcycles", assign_int, int_base+max_dead_cycles_code);@/ +@!@:max\_dead\_cycles\_}{\.{\\maxdeadcycles} primitive@> +primitive("hangafter", assign_int, int_base+hang_after_code);@/ +@!@:hang\_after\_}{\.{\\hangafter} primitive@> +primitive("floatingpenalty", assign_int, int_base+floating_penalty_code);@/ +@!@:floating\_penalty\_}{\.{\\floatingpenalty} primitive@> +primitive("globaldefs", assign_int, int_base+global_defs_code);@/ +@!@:global\_defs\_}{\.{\\globaldefs} primitive@> +primitive("fam", assign_int, int_base+cur_fam_code);@/ +@!@:fam\_}{\.{\\fam} primitive@> +primitive("escapechar", assign_int, int_base+escape_char_code);@/ +@!@:escape\_char\_}{\.{\\escapechar} primitive@> +primitive("defaulthyphenchar", assign_int, int_base+default_hyphen_char_code);@/ +@!@:default\_hyphen\_char\_}{\.{\\defaulthyphenchar} primitive@> +primitive("defaultskewchar", assign_int, int_base+default_skew_char_code);@/ +@!@:default\_skew\_char\_}{\.{\\defaultskewchar} primitive@> +primitive("endlinechar", assign_int, int_base+end_line_char_code);@/ +@!@:end\_line\_char\_}{\.{\\endlinechar} primitive@> +primitive("newlinechar", assign_int, int_base+new_line_char_code);@/ +@!@:new\_line\_char\_}{\.{\\newlinechar} primitive@> +primitive("language", assign_int, int_base+language_code);@/ +@!@:language\_}{\.{\\language} primitive@> +primitive("lefthyphenmin", assign_int, int_base+left_hyphen_min_code);@/ +@!@:left\_hyphen\_min\_}{\.{\\lefthyphenmin} primitive@> +primitive("righthyphenmin", assign_int, int_base+right_hyphen_min_code);@/ +@!@:right\_hyphen\_min\_}{\.{\\righthyphenmin} primitive@> +primitive("holdinginserts", assign_int, int_base+holding_inserts_code);@/ +@!@:holding\_inserts\_}{\.{\\holdinginserts} primitive@> +primitive("errorcontextlines", assign_int, int_base+error_context_lines_code);@/ +@!@:error\_context\_lines\_}{\.{\\errorcontextlines} primitive@> + +@ @= +case assign_int: if (chr_code < count_base) print_param(chr_code-int_base); + else{@+print_esc("count");print_int(chr_code-count_base); + } @+break; + +@ The integer parameters should really be initialized by a macro package; +the following initialization does the minimum to keep \TeX\ from +complete failure. +@^null delimiter@> + +@= +for (k=int_base; k<=del_code_base-1; k++) eqtb[k].i=0; +mag=1000;tolerance=10000;hang_after=1;max_dead_cycles=25; +escape_char='\\';end_line_char=carriage_return; +for (k=0; k<=255; k++) del_code(k)=-1; +del_code('.')=0; /*this null delimiter is used in error recovery*/ + +@ The following procedure, which is called just before \TeX\ initializes its +input and output, establishes the initial values of the date and time. +This does include too, for system integrators, the creation date and +the reference moment for the timer---\Prote\ extensions. If the system +supports environment variables, if |FORCE_SOURCE_DATE| is set to $1$ and +|SOURCE_DATE_EPOCH| is set, the date related values: year, month, day +and time, including creation date, will be taken relative from the value +defined by |SOURCE_DATE_EPOCH|. +@^creation date@> +@^reference time@> +@^system dependencies@> +\TeX\ Live calls |tl_now| to obtain the current time as a |tm| structure. +@p static void fix_date_and_time(void) +{@+ struct tm *t=tl_now(); + time=sys_time= t->tm_hour*60+t->tm_min;/*minutes since midnight*/ + day=sys_day= t->tm_mday;/*day of the month*/ + month=sys_month=t->tm_mon+1;/*month of the year*/ + year=sys_year=t->tm_year+1900;/*Anno Domini*/ +} + +@ @= +{@+if (n < count_base) print_param(n-int_base); +else if (n < del_code_base) + {@+print_esc("count");print_int(n-count_base); + } +else{@+print_esc("delcode");print_int(n-del_code_base); + } +print_char('=');print_int(eqtb[n].i); +} + +@ @=c=escape_char + +@ @=s==new_line_char + +@ \TeX\ is occasionally supposed to print diagnostic information that +goes only into the transcript file, unless |tracing_online| is positive. +Here are two routines that adjust the destination of print commands: + +@p static void begin_diagnostic(void) /*prepare to do some tracing*/ +{@+old_setting=selector; +if ((tracing_online <= 0)&&(selector==term_and_log)) + {@+decr(selector); + if (history==spotless) history=warning_issued; + } +} +@# +static void end_diagnostic(bool @!blank_line) + /*restore proper conditions after tracing*/ +{@+print_nl(""); +if (blank_line) print_ln(); +selector=old_setting; +} + +@ Of course we had better declare a few more global variables, if the previous +routines are going to work. + +@= +static int @!old_setting; +static int @!sys_time, @!sys_day, @!sys_month, @!sys_year; + /*date and time supplied by external system*/ + +@ The final region of |eqtb| contains the dimension parameters defined +here, and the 256 \.{\\dimen} registers. + +@d par_indent_code 0 /*indentation of paragraphs*/ +@d math_surround_code 1 /*space around math in text*/ +@d line_skip_limit_code 2 /*threshold for |line_skip| instead of |baseline_skip|*/ +@d hsize_code 3 /*line width in horizontal mode*/ +@d vsize_code 4 /*page height in vertical mode*/ +@d max_depth_code 5 /*maximum depth of boxes on main pages*/ +@d split_max_depth_code 6 /*maximum depth of boxes on split pages*/ +@d box_max_depth_code 7 /*maximum depth of explicit vboxes*/ +@d hfuzz_code 8 /*tolerance for overfull hbox messages*/ +@d vfuzz_code 9 /*tolerance for overfull vbox messages*/ +@d delimiter_shortfall_code 10 /*maximum amount uncovered by variable delimiters*/ +@d null_delimiter_space_code 11 /*blank space in null delimiters*/ +@d script_space_code 12 /*extra space after subscript or superscript*/ +@d pre_display_size_code 13 /*length of text preceding a display*/ +@d display_width_code 14 /*length of line for displayed equation*/ +@d display_indent_code 15 /*indentation of line for displayed equation*/ +@d overfull_rule_code 16 /*width of rule that identifies overfull hboxes*/ +@d hang_indent_code 17 /*amount of hanging indentation*/ +@d h_offset_code 18 /*amount of horizontal offset when shipping pages out*/ +@d v_offset_code 19 /*amount of vertical offset when shipping pages out*/ +@d emergency_stretch_code 20 /*reduces badnesses on final pass of line-breaking*/ +@d page_width_code 21 /*current paper page width*/ +@d page_height_code 22 /*current paper page height*/ +@d dimen_pars (pdftex_last_dimen_code+1) /*total number of dimension parameters*/ +@d scaled_base (dimen_base+dimen_pars) + /*table of 256 user-defined \.{\\dimen} registers*/ +@d eqtb_size (scaled_base+255) /*largest subscript of |eqtb|*/ +@# +@d dimen(A) eqtb[scaled_base+A].sc +@d dimen_par(A) eqtb[dimen_base+A].sc /*a scaled quantity*/ +@d par_indent dimen_par(par_indent_code) +@d math_surround dimen_par(math_surround_code) +@d line_skip_limit dimen_par(line_skip_limit_code) +@d hsize dimen_par(hsize_code) +@d vsize dimen_par(vsize_code) +@d max_depth dimen_par(max_depth_code) +@d split_max_depth dimen_par(split_max_depth_code) +@d box_max_depth dimen_par(box_max_depth_code) +@d hfuzz dimen_par(hfuzz_code) +@d vfuzz dimen_par(vfuzz_code) +@d delimiter_shortfall dimen_par(delimiter_shortfall_code) +@d null_delimiter_space dimen_par(null_delimiter_space_code) +@d script_space dimen_par(script_space_code) +@d pre_display_size dimen_par(pre_display_size_code) +@d display_width dimen_par(display_width_code) +@d display_indent dimen_par(display_indent_code) +@d overfull_rule dimen_par(overfull_rule_code) +@d hang_indent dimen_par(hang_indent_code) +@d h_offset dimen_par(h_offset_code) +@d v_offset dimen_par(v_offset_code) +@d emergency_stretch dimen_par(emergency_stretch_code) +@d page_height dimen_par(page_height_code) + +@p static void print_length_param(int @!n) +{@+switch (n) { +case par_indent_code: print_esc("parindent");@+break; +case math_surround_code: print_esc("mathsurround");@+break; +case line_skip_limit_code: print_esc("lineskiplimit");@+break; +case hsize_code: print_esc("hsize");@+break; +case vsize_code: print_esc("vsize");@+break; +case max_depth_code: print_esc("maxdepth");@+break; +case split_max_depth_code: print_esc("splitmaxdepth");@+break; +case box_max_depth_code: print_esc("boxmaxdepth");@+break; +case hfuzz_code: print_esc("hfuzz");@+break; +case vfuzz_code: print_esc("vfuzz");@+break; +case delimiter_shortfall_code: print_esc("delimitershortfall");@+break; +case null_delimiter_space_code: print_esc("nulldelimiterspace");@+break; +case script_space_code: print_esc("scriptspace");@+break; +case pre_display_size_code: print_esc("predisplaysize");@+break; +case display_width_code: print_esc("displaywidth");@+break; +case display_indent_code: print_esc("displayindent");@+break; +case overfull_rule_code: print_esc("overfullrule");@+break; +case hang_indent_code: print_esc("hangindent");@+break; +case h_offset_code: print_esc("hoffset");@+break; +case v_offset_code: print_esc("voffset");@+break; +case emergency_stretch_code: print_esc("emergencystretch");@+break; +case page_width_code: + if (pdf_on) print_esc("pdfpagewidth"); + else print_esc("pagewidth"); + @+break; +case page_height_code: + if (pdf_on) print_esc("pdfpageheight"); + else print_esc("pageheight"); + @+break; +@@; +default:print("[unknown dimen parameter!]"); +} +} + +@ @= +primitive("parindent", assign_dimen, dimen_base+par_indent_code);@/ +@!@:par\_indent\_}{\.{\\parindent} primitive@> +primitive("mathsurround", assign_dimen, dimen_base+math_surround_code);@/ +@!@:math\_surround\_}{\.{\\mathsurround} primitive@> +primitive("lineskiplimit", assign_dimen, dimen_base+line_skip_limit_code);@/ +@!@:line\_skip\_limit\_}{\.{\\lineskiplimit} primitive@> +primitive("hsize", assign_dimen, dimen_base+hsize_code);@/ +@!@:hsize\_}{\.{\\hsize} primitive@> +primitive("vsize", assign_dimen, dimen_base+vsize_code);@/ +@!@:vsize\_}{\.{\\vsize} primitive@> +primitive("maxdepth", assign_dimen, dimen_base+max_depth_code);@/ +@!@:max\_depth\_}{\.{\\maxdepth} primitive@> +primitive("splitmaxdepth", assign_dimen, dimen_base+split_max_depth_code);@/ +@!@:split\_max\_depth\_}{\.{\\splitmaxdepth} primitive@> +primitive("boxmaxdepth", assign_dimen, dimen_base+box_max_depth_code);@/ +@!@:box\_max\_depth\_}{\.{\\boxmaxdepth} primitive@> +primitive("hfuzz", assign_dimen, dimen_base+hfuzz_code);@/ +@!@:hfuzz\_}{\.{\\hfuzz} primitive@> +primitive("vfuzz", assign_dimen, dimen_base+vfuzz_code);@/ +@!@:vfuzz\_}{\.{\\vfuzz} primitive@> +primitive("delimitershortfall", + assign_dimen, dimen_base+delimiter_shortfall_code);@/ +@!@:delimiter\_shortfall\_}{\.{\\delimitershortfall} primitive@> +primitive("nulldelimiterspace", + assign_dimen, dimen_base+null_delimiter_space_code);@/ +@!@:null\_delimiter\_space\_}{\.{\\nulldelimiterspace} primitive@> +primitive("scriptspace", assign_dimen, dimen_base+script_space_code);@/ +@!@:script\_space\_}{\.{\\scriptspace} primitive@> +primitive("predisplaysize", assign_dimen, dimen_base+pre_display_size_code);@/ +@!@:pre\_display\_size\_}{\.{\\predisplaysize} primitive@> +primitive("displaywidth", assign_dimen, dimen_base+display_width_code);@/ +@!@:display\_width\_}{\.{\\displaywidth} primitive@> +primitive("displayindent", assign_dimen, dimen_base+display_indent_code);@/ +@!@:display\_indent\_}{\.{\\displayindent} primitive@> +primitive("overfullrule", assign_dimen, dimen_base+overfull_rule_code);@/ +@!@:overfull\_rule\_}{\.{\\overfullrule} primitive@> +primitive("hangindent", assign_dimen, dimen_base+hang_indent_code);@/ +@!@:hang\_indent\_}{\.{\\hangindent} primitive@> +primitive("hoffset", assign_dimen, dimen_base+h_offset_code);@/ +@!@:h\_offset\_}{\.{\\hoffset} primitive@> +primitive("voffset", assign_dimen, dimen_base+v_offset_code);@/ +@!@:v\_offset\_}{\.{\\voffset} primitive@> +primitive("emergencystretch", assign_dimen, dimen_base+emergency_stretch_code);@/ +@!@:emergency\_stretch\_}{\.{\\emergencystretch} primitive@> + +@ @= +case assign_dimen: if (chr_code < scaled_base) + print_length_param(chr_code-dimen_base); + else{@+print_esc("dimen");print_int(chr_code-scaled_base); + } @+break; + +@ @= +for (k=dimen_base; k<=eqtb_size; k++) eqtb[k].sc=0; + +@ @= +{@+if (n < scaled_base) print_length_param(n-dimen_base); +else{@+print_esc("dimen");print_int(n-scaled_base); + } +print_char('=');print_scaled(eqtb[n].sc);print("pt"); +} + +@ Here is a procedure that displays the contents of |eqtb[n]| +symbolically. + +@p @t\4@>@@;@/ +#ifdef @!STAT +static void show_eqtb(pointer @!n) +{@+if (n < active_base) print_char('?'); /*this can't happen*/ +else if (n < glue_base) @@; +else if (n < local_base) @@; +else if (n < int_base) @@; +else if (n < dimen_base) @@; +else if (n <= eqtb_size) @@; +else print_char('?'); /*this can't happen either*/ +} +#endif + +@ The last two regions of |eqtb| have fullword values instead of the +three fields |eq_level|, |eq_type|, and |equiv|. An |eq_type| is unnecessary, +but \TeX\ needs to store the |eq_level| information in another array +called |xeq_level|. + +@= +static memory_word @!eqtb0[eqtb_size-active_base+1], + *const @!eqtb = @!eqtb0-active_base; +static quarterword @!xeq_level0[eqtb_size-int_base+1], + *const @!xeq_level = @!xeq_level0-int_base; + +@ @= +for (k=int_base; k<=eqtb_size; k++) xeq_level[k]=level_one; + +@ When the debugging routine |search_mem| is looking for pointers having a +given value, it is interested only in regions 1 to~3 of~|eqtb|, and in the +first part of region~4. + +@= +for (q=active_base; q<=box_base+255; q++) + {@+if (equiv(q)==p) + {@+print_nl("EQUIV(");print_int(q);print_char(')'); + } + } + +@* The hash table. +Control sequences are stored and retrieved by means of a fairly standard hash +table algorithm called the method of ``coalescing lists'' (cf.\ Algorithm 6.4C +in {\sl The Art of Computer Programming\/}). Once a control sequence enters the +table, it is never removed, because there are complicated situations +involving \.{\\gdef} where the removal of a control sequence at the end of +a group would be a mistake preventable only by the introduction of a +complicated reference-count mechanism. + +The actual sequence of letters forming a control sequence identifier is +stored in the |str_pool| array together with all the other strings. An +auxiliary array |hash| consists of items with two halfword fields per +word. The first of these, called |next(p)|, points to the next identifier +belonging to the same coalesced list as the identifier corresponding to~|p|; +and the other, called |text(p)|, points to the |str_start| entry for +|p|'s identifier. If position~|p| of the hash table is empty, we have +|text(p)==0|; if position |p| is either empty or the end of a coalesced +hash list, we have |next(p)==0|. An auxiliary pointer variable called +|hash_used| is maintained in such a way that all locations |p >= hash_used| +are nonempty. The global variable |cs_count| tells how many multiletter +control sequences have been defined, if statistics are being kept. + +A global boolean variable called |no_new_control_sequence| is set to +|true| during the time that new hash table entries are forbidden. + +@d next(A) hash[A].lh /*link for coalesced lists*/ +@d text(A) hash[A].rh /*string number for control sequence name*/ +@d hash_is_full (hash_used==hash_base) /*test if all positions are occupied*/ +@d font_id_text(A) text(font_id_base+A) /*a frozen font identifier's name*/ + +@= +static two_halves @!hash0[undefined_control_sequence-hash_base], + *const @!hash = @!hash0-hash_base; + /*the hash table*/ +static pointer @!hash_used; /*allocation pointer for |hash|*/ +static bool @!no_new_control_sequence; /*are new identifiers legal?*/ +static int @!cs_count; /*total number of known identifiers*/ + +@ @= +no_new_control_sequence=true; /*new identifiers are usually forbidden*/ +next(hash_base)=0;text(hash_base)=0; +for (k=hash_base+1; k<=undefined_control_sequence-1; k++) hash[k]=hash[hash_base]; + +@ @= +hash_used=frozen_control_sequence; /*nothing is used*/ +cs_count=0; +eq_type(frozen_dont_expand)=dont_expand; +text(frozen_dont_expand)=s_no("notexpanded:"); +@.notexpanded:@> + +@ Here is the subroutine that searches the hash table for an identifier +that matches a given string of length |l > 1| appearing in |buffer[j dotdot +(j+l-1)]|. If the identifier is found, the corresponding hash table address +is returned. Otherwise, if the global variable |no_new_control_sequence| +is |true|, the dummy address |undefined_control_sequence| is returned. +Otherwise the identifier is inserted into the hash table and its location +is returned. + +@p static pointer id_lookup(int @!j, int @!l) /*search the hash table*/ +{@+ /*go here if you found it*/ +int h; /*hash code*/ +int @!d; /*number of characters in incomplete current string*/ +pointer @!p; /*index in |hash| array*/ +int @!k; /*index in |buffer| array*/ +@; +p=h+hash_base; /*we start searching here; note that |0 <= h < hash_prime|*/ +loop@+{@+if (text(p) > 0) if (length(text(p))==l) + if (str_eq_buf(text(p), j)) goto found; + if (next(p)==0) + {@+if (no_new_control_sequence) + p=undefined_control_sequence; + else@; + goto found; + } + p=next(p); + } +found: return p; +} + +@ @= +{@+if (text(p) > 0) + {@+@/do@+{if (hash_is_full) overflow("hash size", hash_size); +@:TeX capacity exceeded hash size}{\quad hash size@> + decr(hash_used); + }@+ while (!(text(hash_used)==0)); /*search for an empty location in |hash|*/ + next(p)=hash_used;p=hash_used; + } +str_room(l);d=cur_length; +while (pool_ptr > str_start[str_ptr]) + {@+decr(pool_ptr);str_pool[pool_ptr+l]=str_pool[pool_ptr]; + } /*move current string up to make room for another*/ +for (k=j; k<=j+l-1; k++) append_char(buffer[k]); +text(p)=make_string();pool_ptr=pool_ptr+d; +#ifdef @!STAT +incr(cs_count); +#endif +@;@/ +} + +@ The value of |hash_prime| should be roughly 85\pct! of |hash_size|, and it +should be a prime number. The theory of hashing tells us to expect fewer +than two table probes, on the average, when the search is successful. +[See J.~S. Vitter, {\sl Journal of the ACM\/ \bf30} (1983), 231--258.] +@^Vitter, Jeffrey Scott@> + +@= +h=buffer[j]; +for (k=j+1; k<=j+l-1; k++) + {@+h=h+h+buffer[k]; + while (h >= hash_prime) h=h-hash_prime; + } + +@ Single-character control sequences do not need to be looked up in a hash +table, since we can use the character code itself as a direct address. +The procedure |print_cs| prints the name of a control sequence, given +a pointer to its address in |eqtb|. A space is printed after the name +unless it is a single nonletter or an active character. This procedure +might be invoked with invalid data, so it is ``extra robust.'' The +individual characters must be printed one at a time using |print|, since +they may be unprintable. + +@= +static void print_cs(int @!p) /*prints a purported control sequence*/ +{@+if (p < hash_base) /*single character*/ + if (p >= single_base) + if (p==null_cs) + {@+print_esc("csname");print_esc("endcsname");print_char(' '); + } + else{@+printn_esc(p-single_base); + if (cat_code(p-single_base)==letter) print_char(' '); + } + else if (p < active_base) print_esc("IMPOSSIBLE."); +@.IMPOSSIBLE@> + else printn(p-active_base); +else if (p >= undefined_control_sequence) print_esc("IMPOSSIBLE."); +else if ((text(p) < 0)||(text(p) >= str_ptr)) print_esc("NONEXISTENT."); +@.NONEXISTENT@> +else{@+if (p==frozen_primitive) print_esc("primitive"); + printn_esc(text(p));print_char(' '); + } +} + +@ Here is a similar procedure; it avoids the error checks, and it never +prints a space after the control sequence. + +@= +static void sprint_cs(pointer @!p) /*prints a control sequence*/ +{@+if (p < hash_base) + if (p < single_base) printn(p-active_base); + else if (p < null_cs) printn_esc(p-single_base); + else{@+print_esc("csname");print_esc("endcsname"); + } +else printn_esc(text(p)); +} + +@ We need to put \TeX's ``primitive'' control sequences into the hash +table, together with their command code (which will be the |eq_type|) +and an operand (which will be the |equiv|). The |primitive| procedure +does this, in a way that no \TeX\ user can. The global value |cur_val| +contains the new |eqtb| pointer after |primitive| has acted. + +@p +#ifdef @!INIT +static void primitive(char *@!str, quarterword @!c, halfword @!o) +{@+str_number s=s_no(str); +int k; /*index into |str_pool|*/ +int @!j; /*index into |buffer|*/ +small_number @!l; /*length of the string*/ +pointer @!p; /*pointer in |ROM|*/ +if (s < 256) cur_val=s+single_base; +else{@+k=str_start[s];l=str_start[s+1]-k; + /*we will move |s| into the (possibly non-empty) |buffer|*/ + if (first+l > buf_size+1) + overflow("buffer size", buf_size); +@:TeX capacity exceeded buffer size}{\quad buffer size@> + for (j=0; j<=l-1; j++) buffer[first+j]=so(str_pool[k+j]); + cur_val=id_lookup(first, l); /*|no_new_control_sequence| is |false|*/ + flush_string;text(cur_val)=s; /*we don't want to have the string twice*/ + } +eq_level(cur_val)=level_one;eq_type(cur_val)=c;equiv(cur_val)=o; +@; +} +#endif + +@ Many of \TeX's primitives need no |equiv|, since they are identifiable +by their |eq_type| alone. These primitives are loaded into the hash table +as follows: + +@= +primitive(" ", ex_space, 0);@/ +@!@:Single-character primitives /}{\quad\.{\\\ }@> +primitive("/", ital_corr, 0);@/ +@!@:Single-character primitives /}{\quad\.{\\/}@> +primitive("accent", accent, 0);@/ +@!@:accent\_}{\.{\\accent} primitive@> +primitive("advance", advance, 0);@/ +@!@:advance\_}{\.{\\advance} primitive@> +primitive("afterassignment", after_assignment, 0);@/ +@!@:after\_assignment\_}{\.{\\afterassignment} primitive@> +primitive("aftergroup", after_group, 0);@/ +@!@:after\_group\_}{\.{\\aftergroup} primitive@> +primitive("begingroup", begin_group, 0);@/ +@!@:begin\_group\_}{\.{\\begingroup} primitive@> +primitive("char", char_num, 0);@/ +@!@:char\_}{\.{\\char} primitive@> +primitive("csname", cs_name, 0);@/ +@!@:cs\_name\_}{\.{\\csname} primitive@> +primitive("delimiter", delim_num, 0);@/ +@!@:delimiter\_}{\.{\\delimiter} primitive@> +primitive("divide", divide, 0);@/ +@!@:divide\_}{\.{\\divide} primitive@> +primitive("endcsname", end_cs_name, 0);@/ +@!@:end\_cs\_name\_}{\.{\\endcsname} primitive@> +primitive("endgroup", end_group, 0); +@!@:end\_group\_}{\.{\\endgroup} primitive@> +text(frozen_end_group)=text(cur_val);eqtb[frozen_end_group]=eqtb[cur_val];@/ +primitive("expandafter", expand_after, 0);@/ +@!@:expand\_after\_}{\.{\\expandafter} primitive@> +primitive("font", def_font, 0);@/ +@!@:font\_}{\.{\\font} primitive@> +primitive("fontdimen", assign_font_dimen, 0);@/ +@!@:font\_dimen\_}{\.{\\fontdimen} primitive@> +primitive("halign", halign, 0);@/ +@!@:halign\_}{\.{\\halign} primitive@> +primitive("hrule", hrule, 0);@/ +@!@:hrule\_}{\.{\\hrule} primitive@> +primitive("ignorespaces", ignore_spaces, 0);@/ +@!@:ignore\_spaces\_}{\.{\\ignorespaces} primitive@> +primitive("insert", insert, 0);@/ +@!@:insert\_}{\.{\\insert} primitive@> +primitive("mark", mark, 0);@/ +@!@:mark\_}{\.{\\mark} primitive@> +primitive("mathaccent", math_accent, 0);@/ +@!@:math\_accent\_}{\.{\\mathaccent} primitive@> +primitive("mathchar", math_char_num, 0);@/ +@!@:math\_char\_}{\.{\\mathchar} primitive@> +primitive("mathchoice", math_choice, 0);@/ +@!@:math\_choice\_}{\.{\\mathchoice} primitive@> +primitive("multiply", multiply, 0);@/ +@!@:multiply\_}{\.{\\multiply} primitive@> +primitive("noalign", no_align, 0);@/ +@!@:no\_align\_}{\.{\\noalign} primitive@> +primitive("noboundary", no_boundary, 0);@/ +@!@:no\_boundary\_}{\.{\\noboundary} primitive@> +primitive("noexpand", no_expand, 0);@/ +@!@:no\_expand\_}{\.{\\noexpand} primitive@> +primitive("nonscript", non_script, 0);@/ +@!@:non\_script\_}{\.{\\nonscript} primitive@> +primitive("omit", omit, 0);@/ +@!@:omit\_}{\.{\\omit} primitive@> +primitive("parshape", set_shape, par_shape_loc);@/ +@!@:par\_shape\_}{\.{\\parshape} primitive@> +primitive("penalty", break_penalty, 0);@/ +@!@:penalty\_}{\.{\\penalty} primitive@> +primitive("prevgraf", set_prev_graf, 0);@/ +@!@:prev\_graf\_}{\.{\\prevgraf} primitive@> +primitive("radical", radical, 0);@/ +@!@:radical\_}{\.{\\radical} primitive@> +primitive("read", read_to_cs, 0);@/ +@!@:read\_}{\.{\\read} primitive@> +primitive("relax", relax, 256); /*cf.\ |scan_file_name|*/ +@!@:relax\_}{\.{\\relax} primitive@> +text(frozen_relax)=text(cur_val);eqtb[frozen_relax]=eqtb[cur_val];@/ +primitive("setbox", set_box, 0);@/ +@!@:set\_box\_}{\.{\\setbox} primitive@> +primitive("the", the, 0);@/ +@!@:the\_}{\.{\\the} primitive@> +primitive("toks", toks_register, mem_bot);@/ +@!@:toks\_}{\.{\\toks} primitive@> +primitive("vadjust", vadjust, 0);@/ +@!@:vadjust\_}{\.{\\vadjust} primitive@> +primitive("valign", valign, 0);@/ +@!@:valign\_}{\.{\\valign} primitive@> +primitive("vcenter", vcenter, 0);@/ +@!@:vcenter\_}{\.{\\vcenter} primitive@> +primitive("vrule", vrule, 0);@/ +@!@:vrule\_}{\.{\\vrule} primitive@> + +@ Each primitive has a corresponding inverse, so that it is possible to +display the cryptic numeric contents of |eqtb| in symbolic form. +Every call of |primitive| in this program is therefore accompanied by some +straightforward code that forms part of the |print_cmd_chr| routine +below. + +@= +case accent: print_esc("accent");@+break; +case advance: print_esc("advance");@+break; +case after_assignment: print_esc("afterassignment");@+break; +case after_group: print_esc("aftergroup");@+break; +case assign_font_dimen: print_esc("fontdimen");@+break; +case begin_group: print_esc("begingroup");@+break; +case break_penalty: print_esc("penalty");@+break; +case char_num: print_esc("char");@+break; +case cs_name: print_esc("csname");@+break; +case def_font: print_esc("font");@+break; +case delim_num: print_esc("delimiter");@+break; +case divide: print_esc("divide");@+break; +case end_cs_name: print_esc("endcsname");@+break; +case end_group: print_esc("endgroup");@+break; +case ex_space: print_esc(" ");@+break; +case expand_after: switch (chr_code) { +case 0: print_esc("expandafter");@+break; +@/@@/ +} @+break; /*there are no other cases*/ +case halign: print_esc("halign");@+break; +case hrule: print_esc("hrule");@+break; +case ignore_spaces: print_esc("ignorespaces");@+break; +case insert: print_esc("insert");@+break; +case ital_corr: print_esc("/");@+break; +case mark: {@+print_esc("mark"); + if (chr_code > 0) print_char('s'); + } @+break; +case math_accent: print_esc("mathaccent");@+break; +case math_char_num: print_esc("mathchar");@+break; +case math_choice: print_esc("mathchoice");@+break; +case multiply: print_esc("multiply");@+break; +case no_align: print_esc("noalign");@+break; +case no_boundary: print_esc("noboundary");@+break; +case no_expand: print_esc("noexpand");@+break; +case non_script: print_esc("nonscript");@+break; +case omit: print_esc("omit");@+break; +case radical: print_esc("radical");@+break; +case read_to_cs: if (chr_code==0) print_esc("read") + @;@+break; +case relax: print_esc("relax");@+break; +case set_box: print_esc("setbox");@+break; +case set_prev_graf: print_esc("prevgraf");@+break; +case set_shape: switch (chr_code) { + case par_shape_loc: print_esc("parshape");@+break; + @@;@/ + } @+break; /*there are no other cases*/ +case the: if (chr_code==0) print_esc("the") + @;@+break; +case toks_register: @@;@+break; +case vadjust: print_esc("vadjust");@+break; +case valign: print_esc("valign");@+break; +case vcenter: print_esc("vcenter");@+break; +case vrule: print_esc("vrule");@+break; + +@ We will deal with the other primitives later, at some point in the program +where their |eq_type| and |equiv| values are more meaningful. For example, +the primitives for math mode will be loaded when we consider the routines +that deal with formulas. It is easy to find where each particular +primitive was treated by looking in the index at the end; for example, the +section where |"radical"| entered |eqtb| is listed under `\.{\\radical} +primitive'. (Primitives consisting of a single nonalphabetic character, +@!like `\.{\\/}', are listed under `Single-character primitives'.) +@!@^Single-character primitives@> + +Meanwhile, this is a convenient place to catch up on something we were unable +to do before the hash table was defined: + +@= +printn_esc(font_id_text(font(p))) + +@* Saving and restoring equivalents. +The nested structure provided by `$\.{\char'173}\ldots\.{\char'175}$' groups +in \TeX\ means that |eqtb| entries valid in outer groups should be saved +and restored later if they are overridden inside the braces. When a new |eqtb| +value is being assigned, the program therefore checks to see if the previous +entry belongs to an outer level. In such a case, the old value is placed +on the |save_stack| just before the new value enters |eqtb|. At the +end of a grouping level, i.e., when the right brace is sensed, the +|save_stack| is used to restore the outer values, and the inner ones are +destroyed. + +Entries on the |save_stack| are of type |memory_word|. The top item on +this stack is |save_stack[p]|, where |p==save_ptr-1|; it contains three +fields called |save_type|, |save_level|, and |save_index|, and it is +interpreted in one of five ways: + +\yskip\hangg 1) If |save_type(p)==restore_old_value|, then +|save_index(p)| is a location in |eqtb| whose current value should +be destroyed at the end of the current group and replaced by |save_stack[p-1]|. +Furthermore if |save_index(p) >= int_base|, then |save_level(p)| +should replace the corresponding entry in |xeq_level|. + +\yskip\hangg 2) If |save_type(p)==restore_zero|, then |save_index(p)| +is a location in |eqtb| whose current value should be destroyed at the end +of the current group, when it should be +replaced by the value of |eqtb[undefined_control_sequence]|. + +\yskip\hangg 3) If |save_type(p)==insert_token|, then |save_index(p)| +is a token that should be inserted into \TeX's input when the current +group ends. + +\yskip\hangg 4) If |save_type(p)==level_boundary|, then |save_level(p)| +is a code explaining what kind of group we were previously in, and +|save_index(p)| points to the level boundary word at the bottom of +the entries for that group. +Furthermore, in extended \eTeX\ mode, |save_stack[p-1]| contains the +source line number at which the current level of grouping was entered. + +\yskip\hang 5) If |save_type(p)==restore_sa|, then |sa_chain| points to a +chain of sparse array entries to be restored at the end of the current +group. Furthermore |save_index(p)| and |save_level(p)| should replace +the values of |sa_chain| and |sa_level| respectively. + +@d save_type(A) save_stack[A].hh.b0 /*classifies a |save_stack| entry*/ +@d save_level(A) save_stack[A].hh.b1 + /*saved level for regions 5 and 6, or group code*/ +@d save_index(A) save_stack[A].hh.rh + /*|eqtb| location or token or |save_stack| location*/ +@d restore_old_value 0 /*|save_type| when a value should be restored later*/ +@d restore_zero 1 /*|save_type| when an undefined entry should be restored*/ +@d insert_token 2 /*|save_type| when a token is being saved for later use*/ +@d level_boundary 3 /*|save_type| corresponding to beginning of group*/ +@d restore_sa 4 /*|save_type| when sparse array entries should be restored*/ + +@p @t\4@>@@; + +@ Here are the group codes that are used to discriminate between different +kinds of groups. They allow \TeX\ to decide what special actions, if any, +should be performed when a group ends. +\def\grp{\.{\char'173...\char'175}} + +Some groups are not supposed to be ended by right braces. For example, +the `\.\$' that begins a math formula causes a |math_shift_group| to +be started, and this should be terminated by a matching `\.\$'. Similarly, +a group that starts with \.{\\left} should end with \.{\\right}, and +one that starts with \.{\\begingroup} should end with \.{\\endgroup}. + +@d bottom_level 0 /*group code for the outside world*/ +@d simple_group 1 /*group code for local structure only*/ +@d hbox_group 2 /*code for `\.{\\hbox}\grp'*/ +@d adjusted_hbox_group 3 /*code for `\.{\\hbox}\grp' in vertical mode*/ +@d vbox_group 4 /*code for `\.{\\vbox}\grp'*/ +@d vtop_group 5 /*code for `\.{\\vtop}\grp'*/ +@d align_group 6 /*code for `\.{\\halign}\grp', `\.{\\valign}\grp'*/ +@d no_align_group 7 /*code for `\.{\\noalign}\grp'*/ +@d output_group 8 /*code for output routine*/ +@d math_group 9 /*code for, e.g., `\.{\char'136}\grp'*/ +@d disc_group 10 /*code for `\.{\\discretionary}\grp\grp\grp'*/ +@d insert_group 11 /*code for `\.{\\insert}\grp', `\.{\\vadjust}\grp'*/ +@d vcenter_group 12 /*code for `\.{\\vcenter}\grp'*/ +@d math_choice_group 13 /*code for `\.{\\mathchoice}\grp\grp\grp\grp'*/ +@d semi_simple_group 14 /*code for `\.{\\begingroup...\\endgroup}'*/ +@d math_shift_group 15 /*code for `\.{\$...\$}'*/ +@d math_left_group 16 /*code for `\.{\\left...\\right}'*/ +@d max_group_code 16 + +@= +typedef int8_t group_code; /*|save_level| for a level boundary*/ + +@ The global variable |cur_group| keeps track of what sort of group we are +currently in. Another global variable, |cur_boundary|, points to the +topmost |level_boundary| word. And |cur_level| is the current depth of +nesting. The routines are designed to preserve the condition that no entry +in the |save_stack| or in |eqtb| ever has a level greater than |cur_level|. + +@ @= +static memory_word @!save_stack[save_size+1]; +static int @!save_ptr; /*first unused entry on |save_stack|*/ +static int @!max_save_stack; /*maximum usage of save stack*/ +static quarterword @!cur_level; /*current nesting level for groups*/ +static group_code @!cur_group; /*current group type*/ +static int @!cur_boundary; /*where the current level begins*/ + +@ At this time it might be a good idea for the reader to review the introduction +to |eqtb| that was given above just before the long lists of parameter names. +Recall that the ``outer level'' of the program is |level_one|, since +undefined control sequences are assumed to be ``defined'' at |level_zero|. + +@= +save_ptr=0;cur_level=level_one;cur_group=bottom_level;cur_boundary=0; +max_save_stack=0; + +@ The following macro is used to test if there is room for up to seven more +entries on |save_stack|. By making a conservative test like this, we can +get by with testing for overflow in only a few places. + +@d check_full_save_stack if (save_ptr > max_save_stack) + {@+max_save_stack=save_ptr; + if (max_save_stack > save_size-7) overflow("save size", save_size); +@:TeX capacity exceeded save size}{\quad save size@> + } + +@ Procedure |new_save_level| is called when a group begins. The +argument is a group identification code like `|hbox_group|'. After +calling this routine, it is safe to put five more entries on |save_stack|. + +In some cases integer-valued items are placed onto the +|save_stack| just below a |level_boundary| word, because this is a +convenient place to keep information that is supposed to ``pop up'' just +when the group has finished. +For example, when `\.{\\hbox to 100pt}\grp' is being treated, the 100pt +dimension is stored on |save_stack| just before |new_save_level| is +called. + +We use the notation |saved(k)| to stand for an integer item that +appears in location |save_ptr+k| of the save stack. + +@d saved(A) save_stack[save_ptr+A].i + +@p static void new_save_level(group_code @!c) /*begin a new level of grouping*/ +{@+check_full_save_stack; +if (eTeX_ex) + {@+saved(0)=line;incr(save_ptr); + } +save_type(save_ptr)=level_boundary;save_level(save_ptr)=cur_group; +save_index(save_ptr)=cur_boundary; +if (cur_level==max_quarterword) overflow("grouping levels", +@:TeX capacity exceeded grouping levels}{\quad grouping levels@> + max_quarterword-min_quarterword); + /*quit if |(cur_level+1)| is too big to be stored in |eqtb|*/ +cur_boundary=save_ptr;cur_group=c; +#ifdef @!STAT +if (tracing_groups > 0) group_trace(false); +#endif +@;@/ +incr(cur_level);incr(save_ptr); +} + +@ Just before an entry of |eqtb| is changed, the following procedure should +be called to update the other data structures properly. It is important +to keep in mind that reference counts in |mem| include references from +within |save_stack|, so these counts must be handled carefully. +@^reference counts@> + +@p static void eq_destroy(memory_word @!w) /*gets ready to forget |w|*/ +{@+pointer q; /*|equiv| field of |w|*/ +switch (eq_type_field(w)) { +case call: case long_call: case outer_call: + case long_outer_call: delete_token_ref(equiv_field(w));@+break; +case glue_ref: delete_glue_ref(equiv_field(w));@+break; +case shape_ref: {@+q=equiv_field(w); /*we need to free a \.{\\parshape} block*/ + if (q!=null) free_node(q, info(q)+info(q)+1); + } @+break; /*such a block is |2 n+1| words long, where |n==info(q)|*/ +case box_ref: flush_node_list(equiv_field(w));@+break; +@/@@/ +default:do_nothing; +} +} + +@ To save a value of |eqtb[p]| that was established at level |l|, we +can use the following subroutine. + +@p static void eq_save(pointer @!p, quarterword @!l) /*saves |eqtb[p]|*/ +{@+check_full_save_stack; +if (l==level_zero) save_type(save_ptr)=restore_zero; +else{@+save_stack[save_ptr]=eqtb[p];incr(save_ptr); + save_type(save_ptr)=restore_old_value; + } +save_level(save_ptr)=l;save_index(save_ptr)=p;incr(save_ptr); +} + +@ The procedure |eq_define| defines an |eqtb| entry having specified +|eq_type| and |equiv| fields, and saves the former value if appropriate. +This procedure is used only for entries in the first four regions of |eqtb|, +i.e., only for entries that have |eq_type| and |equiv| fields. +After calling this routine, it is safe to put four more entries on +|save_stack|, provided that there was room for four more entries before +the call, since |eq_save| makes the necessary test. + +@p +#ifdef @!STAT +#define assign_trace(A, B) if (tracing_assigns > 0) restore_trace(A, B); +#else +#define assign_trace(A, B) +#endif + +static void eq_define(pointer @!p, quarterword @!t, halfword @!e) + /*new data for |eqtb|*/ +{@+ +if (eTeX_ex&&(eq_type(p)==t)&&(equiv(p)==e)) + {@+assign_trace(p,"reassigning")@;@/ + eq_destroy(eqtb[p]);return; + } +assign_trace(p,"changing")@;@/ +if (eq_level(p)==cur_level) eq_destroy(eqtb[p]); +else if (cur_level > level_one) eq_save(p, eq_level(p)); +eq_level(p)=cur_level;eq_type(p)=t;equiv(p)=e; +assign_trace(p,"into")@;@/ +} + +@ The counterpart of |eq_define| for the remaining (fullword) positions in +|eqtb| is called |eq_word_define|. Since |xeq_level[p] >= level_one| for all +|p|, a `|restore_zero|' will never be used in this case. + +@p static void eq_word_define(pointer @!p, int @!w) +{@+ +if (eTeX_ex&&(eqtb[p].i==w)) + {@+assign_trace(p,"reassigning")@;@/ + return; + } +assign_trace(p,"changing")@;@/ +if (xeq_level[p]!=cur_level) + {@+eq_save(p, xeq_level[p]);xeq_level[p]=cur_level; + } +eqtb[p].i=w; +assign_trace(p,"into")@;@/ +} + +@ The |eq_define| and |eq_word_define| routines take care of local definitions. +@^global definitions@> +Global definitions are done in almost the same way, but there is no need +to save old values, and the new value is associated with |level_one|. + +@p static void geq_define(pointer @!p, quarterword @!t, halfword @!e) + /*global |eq_define|*/ +{@+assign_trace(p,"globally changing")@;@/ +{@+eq_destroy(eqtb[p]); +eq_level(p)=level_one;eq_type(p)=t;equiv(p)=e; +} +assign_trace(p,"into");@/ +} +@# +static void geq_word_define(pointer @!p, int @!w) /*global |eq_word_define|*/ +{@+assign_trace(p,"globally changing")@;@/ +{@+eqtb[p].i=w;xeq_level[p]=level_one; +} +assign_trace(p,"into");@/ +} + +@ Subroutine |save_for_after| puts a token on the stack for save-keeping. + +@p static void save_for_after(halfword @!t) +{@+if (cur_level > level_one) + {@+check_full_save_stack; + save_type(save_ptr)=insert_token;save_level(save_ptr)=level_zero; + save_index(save_ptr)=t;incr(save_ptr); + } +} + +@ The |unsave| routine goes the other way, taking items off of |save_stack|. +This routine takes care of restoration when a level ends; everything +belonging to the topmost group is cleared off of the save stack. + +@p +static void back_input(void); +static void unsave(void) /*pops the top level off the save stack*/ +{@+ +pointer p; /*position to be restored*/ +quarterword @!l; /*saved level, if in fullword regions of |eqtb|*/ +halfword @!t; /*saved value of |cur_tok|*/ +bool @!a; /*have we already processed an \.{\\aftergroup} ?*/ +a=false; +if (cur_level > level_one) + {@+decr(cur_level); + @; + } +else confusion("curlevel"); /*|unsave| is not used when |cur_group==bottom_level|*/ +@:this can't happen curlevel}{\quad curlevel@> +} + +@ @= +loop@+{@+decr(save_ptr); + if (save_type(save_ptr)==level_boundary) goto done; + p=save_index(save_ptr); + if (save_type(save_ptr)==insert_token) + @@; + else if (save_type(save_ptr)==restore_sa) + {@+sa_restore();sa_chain=p;sa_level=save_level(save_ptr); + } + else{@+if (save_type(save_ptr)==restore_old_value) + {@+l=save_level(save_ptr);decr(save_ptr); + } + else save_stack[save_ptr]=eqtb[undefined_control_sequence]; + @; + } + } +done: +#ifdef @!STAT +if (tracing_groups > 0) group_trace(true); +#endif +@;@/ +if (grp_stack[in_open]==cur_boundary) group_warning(); + /*groups possibly not properly nested with files*/ +cur_group=save_level(save_ptr);cur_boundary=save_index(save_ptr); +if (eTeX_ex) decr(save_ptr) + +@ A global definition, which sets the level to |level_one|, +@^global definitions@> +will not be undone by |unsave|. If at least one global definition of +|eqtb[p]| has been carried out within the group that just ended, the +last such definition will therefore survive. + +@= +if (p < int_base) + if (eq_level(p)==level_one) + {@+eq_destroy(save_stack[save_ptr]); /*destroy the saved value*/ +#ifdef @!STAT + if (tracing_restores > 0) restore_trace(p,"retaining"); +#endif +@;@/ + } + else{@+eq_destroy(eqtb[p]); /*destroy the current value*/ + eqtb[p]=save_stack[save_ptr]; /*restore the saved value*/ +#ifdef @!STAT + if (tracing_restores > 0) restore_trace(p,"restoring"); +#endif +@;@/ + } +else if (xeq_level[p]!=level_one) + {@+eqtb[p]=save_stack[save_ptr];xeq_level[p]=l; +#ifdef @!STAT + if (tracing_restores > 0) restore_trace(p,"restoring"); +#endif +@;@/ + } +else{ +#ifdef @!STAT + if (tracing_restores > 0) restore_trace(p,"retaining"); +#endif +@;@/ + } + +@ @= +#ifdef @!STAT +static void restore_trace(pointer @!p, char *@!s) + /*|eqtb[p]| has just been restored or retained*/ +{@+begin_diagnostic();print_char('{');print(s);print_char(' '); +show_eqtb(p);print_char('}'); +end_diagnostic(false); +} +#endif + +@ When looking for possible pointers to a memory location, it is helpful +to look for references from |eqtb| that might be waiting on the +save stack. Of course, we might find spurious pointers too; but this +routine is merely an aid when debugging, and at such times we are +grateful for any scraps of information, even if they prove to be irrelevant. +@^dirty \PASCAL@> + +@= +if (save_ptr > 0) for (q=0; q<=save_ptr-1; q++) + {@+if (equiv_field(save_stack[q])==p) + {@+print_nl("SAVE(");print_int(q);print_char(')'); + } + } + +@ Most of the parameters kept in |eqtb| can be changed freely, but there's +an exception: The magnification should not be used with two different +values during any \TeX\ job, since a single magnification is applied to an +entire run. The global variable |mag_set| is set to the current magnification +whenever it becomes necessary to ``freeze'' it at a particular value. + +@= +static int @!mag_set; /*if nonzero, this magnification should be used henceforth*/ + +@ @= +mag_set=0; + +@ The |prepare_mag| subroutine is called whenever \TeX\ wants to use |mag| +for magnification. + +@p static void prepare_mag(void) +{@+if ((mag_set > 0)&&(mag!=mag_set)) + {@+print_err("Incompatible magnification (");print_int(mag); +@.Incompatible magnification@> + print(");");print_nl(" the previous value will be retained"); + help2("I can handle only one magnification ratio per job. So I've",@/ + "reverted to the magnification you used earlier on this run.");@/ + int_error(mag_set); + geq_word_define(int_base+mag_code, mag_set); /*|mag=mag_set|*/ + } +if ((mag <= 0)||(mag > 32768)) + {@+print_err("Illegal magnification has been changed to 1000");@/ +@.Illegal magnification...@> + help1("The magnification ratio must be between 1 and 32768."); + int_error(mag);geq_word_define(int_base+mag_code, 1000); + } +mag_set=mag; +} + +@* Token lists. +A \TeX\ token is either a character or a control sequence, and it is +@^token@> +represented internally in one of two ways: (1)~A character whose ASCII +code number is |c| and whose command code is |m| is represented as the +number $2^8m+c$; the command code is in the range |1 <= m <= 14|. (2)~A control +sequence whose |eqtb| address is |p| is represented as the number +|cs_token_flag+p|. Here |cs_token_flag==@t$2^{12}-1$@>| is larger than +$2^8m+c$, yet it is small enough that |cs_token_flag+p < max_halfword|; +thus, a token fits comfortably in a halfword. + +A token |t| represents a |left_brace| command if and only if +|t < left_brace_limit|; it represents a |right_brace| command if and only if +we have |left_brace_limit <= t < right_brace_limit|; and it represents a |match| or +|end_match| command if and only if |match_token <= t <= end_match_token|. +The following definitions take care of these token-oriented constants +and a few others. + +@d cs_token_flag 07777 /*amount added to the |eqtb| location in a + token that stands for a control sequence; is a multiple of~256, less~1*/ +@d left_brace_token 00400 /*$2^8\cdot|left_brace|$*/ +@d left_brace_limit 01000 /*$2^8\cdot(|left_brace|+1)$*/ +@d right_brace_token 01000 /*$2^8\cdot|right_brace|$*/ +@d right_brace_limit 01400 /*$2^8\cdot(|right_brace|+1)$*/ +@d math_shift_token 01400 /*$2^8\cdot|math_shift|$*/ +@d tab_token 02000 /*$2^8\cdot|tab_mark|$*/ +@d out_param_token 02400 /*$2^8\cdot|out_param|$*/ +@d space_token 05040 /*$2^8\cdot|spacer|+|' '|$*/ +@d letter_token 05400 /*$2^8\cdot|letter|$*/ +@d other_token 06000 /*$2^8\cdot|other_char|$*/ +@d match_token 06400 /*$2^8\cdot|match|$*/ +@d end_match_token 07000 /*$2^8\cdot|end_match|$*/ +@d protected_token 07001 /*$2^8\cdot|end_match|+1$*/ + +@ @= +if (cs_token_flag+undefined_control_sequence > max_halfword) bad=21; + +@ A token list is a singly linked list of one-word nodes in |mem|, where +each word contains a token and a link. Macro definitions, output-routine +definitions, marks, \.{\\write} texts, and a few other things +are remembered by \TeX\ in the form +of token lists, usually preceded by a node with a reference count in its +|token_ref_count| field. The token stored in location |p| is called +|info(p)|. + +Three special commands appear in the token lists of macro definitions. +When |m==match|, it means that \TeX\ should scan a parameter +for the current macro; when |m==end_match|, it means that parameter +matching should end and \TeX\ should start reading the macro text; and +when |m==out_param|, it means that \TeX\ should insert parameter +number |c| into the text at this point. + +The enclosing \.{\char'173} and \.{\char'175} characters of a macro +definition are omitted, but an output routine +will be enclosed in braces. + +Here is an example macro definition that illustrates these conventions. +After \TeX\ processes the text +$$\.{\\def\\mac a\#1\#2 \\b \{\#1\\-a \#\#1\#2 \#2\}}$$ +the definition of \.{\\mac} is represented as a token list containing +$$\def\,{\hskip2pt} +\vbox{\halign{\hfil#\hfil\cr +(reference count), |letter|\,\.a, |match|\,\#, |match|\,\#, |spacer|\,\.\ , +\.{\\b}, |end_match|,\cr +|out_param|\,1, \.{\\-}, |letter|\,\.a, |spacer|\,\.\ , |mac_param|\,\#, +|other_char|\,\.1,\cr +|out_param|\,2, |spacer|\,\.\ , |out_param|\,2.\cr}}$$ +The procedure |scan_toks| builds such token lists, and |macro_call| +does the parameter matching. +@^reference counts@> + +Examples such as +$$\.{\\def\\m\{\\def\\m\{a\}\ b\}}$$ +explain why reference counts would be needed even if \TeX\ had no \.{\\let} +operation: When the token list for \.{\\m} is being read, the redefinition of +\.{\\m} changes the |eqtb| entry before the token list has been fully +consumed, so we dare not simply destroy a token list when its +control sequence is being redefined. + +If the parameter-matching part of a definition ends with `\.{\#\{}', +the corresponding token list will have `\.\{' just before the `|end_match|' +and also at the very end. The first `\.\{' is used to delimit the parameter; the +second one keeps the first from disappearing. + +@ The procedure |show_token_list|, which prints a symbolic form of +the token list that starts at a given node |p|, illustrates these +conventions. The token list being displayed should not begin with a reference +count. However, the procedure is intended to be robust, so that if the +memory links are awry or if |p| is not really a pointer to a token list, +nothing catastrophic will happen. + +An additional parameter |q| is also given; this parameter is either null +or it points to a node in the token list where a certain magic computation +takes place that will be explained later. (Basically, |q| is non-null when +we are printing the two-line context information at the time of an error +message; |q| marks the place corresponding to where the second line +should begin.) + +For example, if |p| points to the node containing the first \.a in the +token list above, then |show_token_list| will print the string +$$\hbox{`\.{a\#1\#2\ \\b\ ->\#1\\-a\ \#\#1\#2\ \#2}';}$$ +and if |q| points to the node containing the second \.a, +the magic computation will be performed just before the second \.a is printed. + +The generation will stop, and `\.{\\ETC.}' will be printed, if the length +of printing exceeds a given limit~|l|. Anomalous entries are printed in the +form of control sequences that are not followed by a blank space, e.g., +`\.{\\BAD.}'; this cannot be confused with actual control sequences because +a real control sequence named \.{BAD} would come out `\.{\\BAD\ }'. + +@= +static void show_token_list(int @!p, int @!q, int @!l) +{@+ +int m, @!c; /*pieces of a token*/ +ASCII_code @!match_chr; /*character used in a `|match|'*/ +ASCII_code @!n; /*the highest parameter number, as an ASCII digit*/ +match_chr='#';n='0';tally=0; +while ((p!=null)&&(tally < l)) + {@+if (p==q) @; + @; + p=link(p); + } +if (p!=null) print_esc("ETC."); +@.ETC@> + +} + +@ @= +if ((p < hi_mem_min)||(p > mem_end)) + {@+print_esc("CLOBBERED.");return; +@.CLOBBERED@> + } +if (info(p) >= cs_token_flag) print_cs(info(p)-cs_token_flag); +else{@+m=info(p)/0400;c=info(p)%0400; + if (info(p) < 0) print_esc("BAD."); +@.BAD@> + else@; + } + +@ The procedure usually ``learns'' the character code used for macro +parameters by seeing one in a |match| command before it runs into any +|out_param| commands. + +@= +switch (m) { +case left_brace: case right_brace: case math_shift: + case tab_mark: case sup_mark: case sub_mark: + case spacer: + case letter: case other_char: printn(c);@+break; +case mac_param: {@+printn(c);printn(c); + } @+break; +case out_param: {@+printn(match_chr); + if (c <= 9) print_char(c+'0'); + else{@+print_char('!');return; + } + } @+break; +case match: {@+match_chr=c;printn(c);incr(n);print_char(n); + if (n > '9') return; + } @+break; +case end_match: if (c==0) print("->");@+break; +@.->@> +default:print_esc("BAD."); +@.BAD@> +} + +@ Here's the way we sometimes want to display a token list, given a pointer +to its reference count; the pointer may be null. + +@p static void token_show(pointer @!p) +{@+if (p!=null) show_token_list(link(p), null, 10000000); +} + +@ The |print_meaning| subroutine displays |cur_cmd| and |cur_chr| in +symbolic form, including the expansion of a macro or mark. + +@p static void print_meaning(void) +{@+print_cmd_chr(cur_cmd, cur_chr); +if (cur_cmd >= call) + {@+print_char(':');print_ln();token_show(cur_chr); + } +else if ((cur_cmd==top_bot_mark)&&(cur_chr < marks_code)) + {@+print_char(':');print_ln(); + token_show(cur_mark[cur_chr]); + } +} + +@* Introduction to the syntactic routines. +Let's pause a moment now and try to look at the Big Picture. +The \TeX\ program consists of three main parts: syntactic routines, +semantic routines, and output routines. The chief purpose of the +syntactic routines is to deliver the user's input to the semantic routines, +one token at a time. The semantic routines act as an interpreter +responding to these tokens, which may be regarded as commands. And the +output routines are periodically called on to convert box-and-glue +lists into a compact set of instructions that will be sent +to a typesetter. We have discussed the basic data structures and utility +routines of \TeX, so we are good and ready to plunge into the real activity by +considering the syntactic routines. + +Our current goal is to come to grips with the |get_next| procedure, +which is the keystone of \TeX's input mechanism. Each call of |get_next| +sets the value of three variables |cur_cmd|, |cur_chr|, and |cur_cs|, +representing the next input token. +$$\vbox{\halign{#\hfil\cr + \hbox{|cur_cmd| denotes a command code from the long list of codes + given above;}\cr + \hbox{|cur_chr| denotes a character code or other modifier of the command + code;}\cr + \hbox{|cur_cs| is the |eqtb| location of the current control sequence,}\cr + \hbox{\qquad if the current token was a control sequence, + otherwise it's zero.}\cr}}$$ +Underlying this external behavior of |get_next| is all the machinery +necessary to convert from character files to tokens. At a given time we +may be only partially finished with the reading of several files (for +which \.{\\input} was specified), and partially finished with the expansion +of some user-defined macros and/or some macro parameters, and partially +finished with the generation of some text in a template for \.{\\halign}, +and so on. When reading a character file, special characters must be +classified as math delimiters, etc.; comments and extra blank spaces must +be removed, paragraphs must be recognized, and control sequences must be +found in the hash table. Furthermore there are occasions in which the +scanning routines have looked ahead for a word like `\.{plus}' but only +part of that word was found, hence a few characters must be put back +into the input and scanned again. + +To handle these situations, which might all be present simultaneously, +\TeX\ uses various stacks that hold information about the incomplete +activities, and there is a finite state control for each level of the +input mechanism. These stacks record the current state of an implicitly +recursive process, but the |get_next| procedure is not recursive. +Therefore it will not be difficult to translate these algorithms into +low-level languages that do not support recursion. + +@= +static eight_bits @!cur_cmd; /*current command set by |get_next|*/ +static halfword @!cur_chr; /*operand of current command*/ +static pointer @!cur_cs; /*control sequence found here, zero if none found*/ +static halfword @!cur_tok; /*packed representative of |cur_cmd| and |cur_chr|*/ + +@ The |print_cmd_chr| routine prints a symbolic interpretation of a +command code and its modifier. This is used in certain `\.{You can\'t}' +error messages, and in the implementation of diagnostic routines like +\.{\\show}. + +The body of |print_cmd_chr| is a rather tedious listing of print +commands, and most of it is essentially an inverse to the |primitive| +routine that enters a \TeX\ primitive into |eqtb|. Therefore much of +this procedure appears elsewhere in the program, +together with the corresponding |primitive| calls. + +@d chr_cmd(A) {@+print(A);print_ASCII(chr_code); + } + +@= +static void print_cmd_chr(quarterword @!cmd, halfword @!chr_code) +{@+int n; /*temp variable*/ +switch (cmd) { +case left_brace: chr_cmd("begin-group character ")@;@+break; +case right_brace: chr_cmd("end-group character ")@;@+break; +case math_shift: chr_cmd("math shift character ")@;@+break; +case mac_param: chr_cmd("macro parameter character ")@;@+break; +case sup_mark: chr_cmd("superscript character ")@;@+break; +case sub_mark: chr_cmd("subscript character ")@;@+break; +case endv: print("end of alignment template");@+break; +case spacer: chr_cmd("blank space ")@;@+break; +case letter: chr_cmd("the letter ")@;@+break; +case other_char: chr_cmd("the character ")@;@+break; +@t\4@>@@/ +default:print("[unknown command code!]"); +} +} + +@ Here is a procedure that displays the current command. + +@p static void show_cur_cmd_chr(void) +{@+int n; /*level of \.{\\if...\\fi} nesting*/ +int @!l; /*line where \.{\\if} started*/ +pointer @!p; +begin_diagnostic();print_nl("{"); +if (mode!=shown_mode) + {@+print_mode(mode);print(": ");shown_mode=mode; + } +print_cmd_chr(cur_cmd, cur_chr); +if (tracing_ifs > 0) + if (cur_cmd >= if_test) if (cur_cmd <= fi_or_else) + {@+print(": "); + if (cur_cmd==fi_or_else) + {@+print_cmd_chr(if_test, cur_if);print_char(' '); + n=0;l=if_line; + } + else{@+n=1;l=line; + } + p=cond_ptr; + while (p!=null) + {@+incr(n);p=link(p); + } + print("(level ");print_int(n);print_char(')');print_if_line(l); + } +print_char('}'); +end_diagnostic(false); +} + +@* Input stacks and states. +This implementation of +\TeX\ uses two different conventions for representing sequential stacks. +@^stack conventions@>@^conventions for representing stacks@> + +\yskip\hangg 1) If there is frequent access to the top entry, and if the +stack is essentially never empty, then the top entry is kept in a global +variable (even better would be a machine register), and the other entries +appear in the array $\\{stack}[0\to(\\{ptr}-1)]$. For example, the +semantic stack described above is handled this way, and so is the input +stack that we are about to study. + +\yskip\hangg 2) If there is infrequent top access, the entire stack contents +are in the array $\\{stack}[0\to(\\{ptr}-1)]$. For example, the |save_stack| +is treated this way, as we have seen. + +\yskip\noindent +The state of \TeX's input mechanism appears in the input stack, whose +entries are records with six fields, called |state|, |index|, |start|, |loc|, +|limit|, and |name|. This stack is maintained with +convention~(1), so it is declared in the following way: + +@= +typedef struct { + quarterword @!state_field, @!index_field; + halfword @!start_field, @!loc_field, @!limit_field, @!name_field; + halfword @!depth_field; + } in_state_record; + +@ @= +static in_state_record @!input_stack[stack_size+1]; +static int @!input_ptr; /*first unused location of |input_stack|*/ +static int @!max_in_stack; /*largest value of |input_ptr| when pushing*/ +static in_state_record @!cur_input; + /*the ``top'' input state, according to convention (1)*/ + +@ We've already defined the special variable |loc==cur_input.loc_field| +in our discussion of basic input-output routines. The other components of +|cur_input| are defined in the same way: + +@d state cur_input.state_field /*current scanner state*/ +@d index cur_input.index_field /*reference for buffer information*/ +@d start cur_input.start_field /*starting position in |buffer|*/ +@d limit cur_input.limit_field /*end of current line in |buffer|*/ +@d name cur_input.name_field /*name of the current file*/ +@d cur_depth cur_input.depth_field /* nesting depth of current macro */ + +@ Let's look more closely now at the control variables +(|state|,~|index|,~|start|,~|loc|,~|limit|,~|name|), +assuming that \TeX\ is reading a line of characters that have been input +from some file or from the user's terminal. There is an array called +|buffer| that acts as a stack of all lines of characters that are +currently being read from files, including all lines on subsidiary +levels of the input stack that are not yet completed. \TeX\ will return to +the other lines when it is finished with the present input file. + +(Incidentally, on a machine with byte-oriented addressing, it might be +appropriate to combine |buffer| with the |str_pool| array, +letting the buffer entries grow downward from the top of the string pool +and checking that these two tables don't bump into each other.) + +The line we are currently working on begins in position |start| of the +buffer; the next character we are about to read is |buffer[loc]|; and +|limit| is the location of the last character present. If |loc > limit|, +the line has been completely read. Usually |buffer[limit]| is the +|end_line_char|, denoting the end of a line, but this is not +true if the current line is an insertion that was entered on the user's +terminal in response to an error message. + +The |name| variable is a string number that designates the name of +the current file, if we are reading a text file. It is zero if we +are reading from the terminal; it is |n+1| if we are reading from +input stream |n|, where |0 <= n <= 16|. (Input stream 16 stands for +an invalid stream number; in such cases the input is actually from +the terminal, under control of the procedure |read_toks|.) +Finally |18 <= name <= 19| indicates that we are reading a pseudo file +created by the \.{\\scantokens} command. + +The |state| variable has one of three values, when we are scanning such +files: +$$\baselineskip 15pt\vbox{\halign{#\hfil\cr +1) |state==mid_line| is the normal state.\cr +2) |state==skip_blanks| is like |mid_line|, but blanks are ignored.\cr +3) |state==new_line| is the state at the beginning of a line.\cr}}$$ +These state values are assigned numeric codes so that if we add the state +code to the next character's command code, we get distinct values. For +example, `|mid_line+spacer|' stands for the case that a blank +space character occurs in the middle of a line when it is not being +ignored; after this case is processed, the next value of |state| will +be |skip_blanks|. + +@d mid_line 1 /*|state| code when scanning a line of characters*/ +@d skip_blanks (2+max_char_code) /*|state| code when ignoring blanks*/ +@d new_line (3+max_char_code+max_char_code) /*|state| code at start of line*/ + +@ Additional information about the current line is available via the +|index| variable, which counts how many lines of characters are present +in the buffer below the current level. We have |index==0| when reading +from the terminal and prompting the user for each line; then if the user types, +e.g., `\.{\\input paper}', we will have |index==1| while reading +the file \.{paper.tex}. However, it does not follow that |index| is the +same as the input stack pointer, since many of the levels on the input +stack may come from token lists. For example, the instruction `\.{\\input +paper}' might occur in a token list. + +The global variable |in_open| is equal to the |index| +value of the highest non-token-list level. Thus, the number of partially read +lines in the buffer is |in_open+1|, and we have |in_open==index| +when we are not reading a token list. + +If we are not currently reading from the terminal, or from an input +stream, we are reading from the file variable |input_file[index]|. We use +the notation |terminal_input| as a convenient abbreviation for |name==0|, +and |cur_file| as an abbreviation for |input_file[index]|. + +The global variable |line| contains the line number in the topmost +open file, for use in error messages. If we are not reading from +the terminal, |line_stack[index]| holds the line number for the +enclosing level, so that |line| can be restored when the current +file has been read. Line numbers should never be negative, since the +negative of the current line number is used to identify the user's output +routine in the |mode_line| field of the semantic nest entries. + +If more information about the input state is needed, it can be +included in small arrays like those shown here. For example, +the current page or segment number in the input file might be +put into a variable |@!page|, maintained for enclosing levels in +`\ignorespaces|@!page_stack: array[1 dotdot max_in_open]int|\unskip' +by analogy with |line_stack|. +@^system dependencies@> + +@d terminal_input (name==0) /*are we reading from the terminal?*/ +@d cur_file input_file[index] /*the current |alpha_file| variable*/ + +@= +static int @!in_open; /*the number of lines in the buffer, less one*/ +static int @!open_parens; /*the number of open text files*/ +static alpha_file @!input_file0[max_in_open], + *const @!input_file = @!input_file0-1; +static int @!line; /*current line number in the current source file*/ +static int @!line_stack0[max_in_open], + *const @!line_stack = @!line_stack0-1; + +@ Users of \TeX\ sometimes forget to balance left and right braces properly, +and one of the ways \TeX\ tries to spot such errors is by considering an +input file as broken into subfiles by control sequences that +are declared to be \.{\\outer}. + +A variable called |scanner_status| tells \TeX\ whether or not to complain +when a subfile ends. This variable has six possible values: + +\yskip\hang|normal|, means that a subfile can safely end here without incident. + +\yskip\hang|skipping|, means that a subfile can safely end here, but not a file, +because we're reading past some conditional text that was not selected. + +\yskip\hang|defining|, means that a subfile shouldn't end now because a +macro is being defined. + +\yskip\hang|matching|, means that a subfile shouldn't end now because a +macro is being used and we are searching for the end of its arguments. + +\yskip\hang|aligning|, means that a subfile shouldn't end now because we are +not finished with the preamble of an \.{\\halign} or \.{\\valign}. + +\yskip\hang|absorbing|, means that a subfile shouldn't end now because we are +reading a balanced token list for \.{\\message}, \.{\\write}, etc. + +\yskip\noindent +If the |scanner_status| is not |normal|, the variable |warning_index| points +to the |eqtb| location for the relevant control sequence name to print +in an error message. + +@d skipping 1 /*|scanner_status| when passing conditional text*/ +@d defining 2 /*|scanner_status| when reading a macro definition*/ +@d matching 3 /*|scanner_status| when reading macro arguments*/ +@d aligning 4 /*|scanner_status| when reading an alignment preamble*/ +@d absorbing 5 /*|scanner_status| when reading a balanced text*/ + +@= +static int @!scanner_status; /*can a subfile end now?*/ +static pointer @!warning_index; /*identifier relevant to non-|normal| scanner status*/ +static pointer @!def_ref; /*reference count of token list being defined*/ + +@ Here is a procedure that uses |scanner_status| to print a warning message +when a subfile has ended, and at certain other crucial times: + +@= +static void runaway(void) +{@+pointer p; /*head of runaway list*/ +if (scanner_status > skipping) + {@+print_nl("Runaway "); +@.Runaway...@> + switch (scanner_status) { + case defining: {@+print("definition");p=def_ref; + } @+break; + case matching: {@+print("argument");p=temp_head; + } @+break; + case aligning: {@+print("preamble");p=hold_head; + } @+break; + case absorbing: {@+print("text");p=def_ref; + } + } /*there are no other cases*/ + print_char('?');print_ln();show_token_list(link(p), null, error_line-10); + } +} + +@ However, all this discussion about input state really applies only to the +case that we are inputting from a file. There is another important case, +namely when we are currently getting input from a token list. In this case +|state==token_list|, and the conventions about the other state variables +are different: + +\yskip\hang|loc| is a pointer to the current node in the token list, i.e., +the node that will be read next. If |loc==null|, the token list has been +fully read. + +\yskip\hang|start| points to the first node of the token list; this node +may or may not contain a reference count, depending on the type of token +list involved. + +\yskip\hang|token_type|, which takes the place of |index| in the +discussion above, is a code number that explains what kind of token list +is being scanned. + +\yskip\hang|name| points to the |eqtb| address of the control sequence +being expanded, if the current token list is a macro. + +\yskip\hang|param_start|, which takes the place of |limit|, tells where +the parameters of the current macro begin in the |param_stack|, if the +current token list is a macro. + +\yskip\noindent The |token_type| can take several values, depending on +where the current token list came from: + +\yskip\hang|parameter|, if a parameter is being scanned; + +\hang|u_template|, if the \ part of an alignment +template is being scanned; + +\hang|v_template|, if the \ part of an alignment +template is being scanned; + +\hang|backed_up|, if the token list being scanned has been inserted as +`to be read again'; + +\hang|inserted|, if the token list being scanned has been inserted as +the text expansion of a \.{\\count} or similar variable; + +\hang|macro|, if a user-defined control sequence is being scanned; + +\hang|output_text|, if an \.{\\output} routine is being scanned; + +\hang|every_par_text|, if the text of \.{\\everypar} is being scanned; + +\hang|every_math_text|, if the text of \.{\\everymath} is being scanned; + +\hang|every_display_text|, if the text of \.{\\everydisplay} is being scanned; + +\hang|every_hbox_text|, if the text of \.{\\everyhbox} is being scanned; + +\hang|every_vbox_text|, if the text of \.{\\everyvbox} is being scanned; + +\hang|every_job_text|, if the text of \.{\\everyjob} is being scanned; + +\hang|every_cr_text|, if the text of \.{\\everycr} is being scanned; + +\hang|mark_text|, if the text of a \.{\\mark} is being scanned; + +\hang|write_text|, if the text of a \.{\\write} is being scanned. + +\yskip\noindent +The codes for |output_text|, |every_par_text|, etc., are equal to a constant +plus the corresponding codes for token list parameters |output_routine_loc|, +|every_par_loc|, etc. The token list begins with a reference count if and +only if |token_type >= macro|. +@^reference counts@> + +Since \eTeX's additional token list parameters precede |toks_base|, the +corresponding token types must precede |write_text|. + +@d token_list 0 /*|state| code when scanning a token list*/ +@d token_type index /*type of current token list*/ +@d param_start limit /*base of macro parameters in |param_stack|*/ +@d parameter 0 /*|token_type| code for parameter*/ +@d u_template 1 /*|token_type| code for \ template*/ +@d v_template 2 /*|token_type| code for \ template*/ +@d backed_up 3 /*|token_type| code for text to be reread*/ +@d inserted 4 /*|token_type| code for inserted texts*/ +@d macro 5 /*|token_type| code for defined control sequences*/ +@d output_text 6 /*|token_type| code for output routines*/ +@d every_par_text 7 /*|token_type| code for \.{\\everypar}*/ +@d every_math_text 8 /*|token_type| code for \.{\\everymath}*/ +@d every_display_text 9 /*|token_type| code for \.{\\everydisplay}*/ +@d every_hbox_text 10 /*|token_type| code for \.{\\everyhbox}*/ +@d every_vbox_text 11 /*|token_type| code for \.{\\everyvbox}*/ +@d every_job_text 12 /*|token_type| code for \.{\\everyjob}*/ +@d every_cr_text 13 /*|token_type| code for \.{\\everycr}*/ +@d mark_text 14 /*|token_type| code for \.{\\topmark}, etc.*/ +@# +@d eTeX_text_offset (output_routine_loc-output_text) +@d every_eof_text (every_eof_loc-eTeX_text_offset) + /*|token_type| code for \.{\\everyeof}*/ +@# +@d write_text (toks_base-eTeX_text_offset) /*|token_type| code for \.{\\write}*/ + +@ The |param_stack| is an auxiliary array used to hold pointers to the token +lists for parameters at the current level and subsidiary levels of input. +This stack is maintained with convention (2), and it grows at a different +rate from the others. + +@= +static pointer @!param_stack[param_size+1]; + /*token list pointers for parameters*/ +static int @!param_ptr; /*first unused entry in |param_stack|*/ +static int @!max_param_stack; + /*largest value of |param_ptr|, will be | <= param_size+9|*/ + +@ The input routines must also interact with the processing of +\.{\\halign} and \.{\\valign}, since the appearance of tab marks and +\.{\\cr} in certain places is supposed to trigger the beginning of special +\ template text in the scanner. This magic is accomplished by an +|align_state| variable that is increased by~1 when a `\.{\char'173}' is +scanned and decreased by~1 when a `\.{\char'175}' is scanned. The |align_state| +is nonzero during the \ template, after which it is set to zero; the +\ template begins when a tab mark or \.{\\cr} occurs at a time that +|align_state==0|. + +The same principle applies when entering the definition of a +control sequence between \.{\\csname} and \.{\\endcsname}. + +@= +static int @!align_state; /*group level with respect to current alignment*/ +static int @!incsname_state; /*group level with respect to in csname state*/ + +@ Thus, the ``current input state'' can be very complicated indeed; there +can be many levels and each level can arise in a variety of ways. The +|show_context| procedure, which is used by \TeX's error-reporting routine to +print out the current input state on all levels down to the most recent +line of characters from an input file, illustrates most of these conventions. +The global variable |base_ptr| contains the lowest level that was +displayed by this procedure. + +@= +static int @!base_ptr; /*shallowest level shown by |show_context|*/ + +@ The status at each level is indicated by printing two lines, where the first +line indicates what was read so far and the second line shows what remains +to be read. The context is cropped, if necessary, so that the first line +contains at most |half_error_line| characters, and the second contains +at most |error_line|. Non-current input levels whose |token_type| is +`|backed_up|' are shown only if they have not been fully read. + +@p static void show_context(void) /*prints where the scanner is*/ +{@+ +int old_setting; /*saved |selector| setting*/ +int @!nn; /*number of contexts shown so far, less one*/ +bool @!bottom_line; /*have we reached the final context to be shown?*/ +@@/ +base_ptr=input_ptr;input_stack[base_ptr]=cur_input; + /*store current state*/ +nn=-1;bottom_line=false; +loop@+{@+cur_input=input_stack[base_ptr]; /*enter into the context*/ + if ((state!=token_list)) + if ((name > 19)||(base_ptr==0)) bottom_line=true; + if ((base_ptr==input_ptr)||bottom_line||(nn < error_context_lines)) + @@; + else if (nn==error_context_lines) + {@+print_nl("...");incr(nn); /*omitted if |error_context_lines < 0|*/ + } + if (bottom_line) goto done; + decr(base_ptr); + } +done: cur_input=input_stack[input_ptr]; /*restore original state*/ +} + +@ @= +{@+if ((base_ptr==input_ptr)||(state!=token_list)|| + (token_type!=backed_up)||(loc!=null)) + /*we omit backed-up token lists that have already been read*/ + {@+tally=0; /*get ready to count characters*/ + old_setting=selector; + if (state!=token_list) + {@+@; + @; + } + else{@+@; + @; + } + selector=old_setting; /*stop pseudoprinting*/ + @; + incr(nn); + } +} + +@ This routine should be changed, if necessary, to give the best possible +indication of where the current line resides in the input file. +For example, on some systems it is best to print both a page and line number. +@^system dependencies@> + +@= +if (name <= 17) + if (terminal_input) + if (base_ptr==0) print_nl("<*>");else print_nl(" "); + else{@+print_nl(" + print_char('>'); + } +else{@+print_nl("l."); + if (index==in_open) print_int(line); + else print_int(line_stack[index+1]); /*input from a pseudo file*/ + } +print_char(' ') + +@ @= +switch (token_type) { +case parameter: print_nl(" ");@+break; +case u_template: case v_template: print_nl("