mdk-1.3.1/ 0000775 0001750 0001750 00000000000 15065042311 006027 5 mdk-1.3.1/config.sub 0000755 0001750 0001750 00000115441 14770044664 007755 #! /bin/sh
# Configuration validation subroutine script.
# Copyright 1992-2024 Free Software Foundation, Inc.
# shellcheck disable=SC2006,SC2268,SC2162 # see below for rationale
timestamp='2024-05-27'
# This file is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, see .
#
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that
# program. This Exception is an additional permission under section 7
# of the GNU General Public License, version 3 ("GPLv3").
# Please send patches to .
#
# Configuration subroutine to validate and canonicalize a configuration type.
# Supply the specified configuration type as an argument.
# If it is invalid, we print an error message on stderr and exit with code 1.
# Otherwise, we print the canonical config type on stdout and succeed.
# You can get the latest version of this script from:
# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
# This file is supposed to be the same for all GNU packages
# and recognize all the CPU types, system types and aliases
# that are meaningful with *any* GNU software.
# Each package is responsible for reporting which valid configurations
# it does not support. The user should be able to distinguish
# a failure to support a valid configuration from a meaningless
# configuration.
# The goal of this file is to map all the various variations of a given
# machine specification into a single specification in the form:
# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
# or in some cases, the newer four-part form:
# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
# It is wrong to echo any other type of specification.
# The "shellcheck disable" line above the timestamp inhibits complaints
# about features and limitations of the classic Bourne shell that were
# superseded or lifted in POSIX. However, this script identifies a wide
# variety of pre-POSIX systems that do not have POSIX shells at all, and
# even some reasonably current systems (Solaris 10 as case-in-point) still
# have a pre-POSIX /bin/sh.
me=`echo "$0" | sed -e 's,.*/,,'`
usage="\
Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
Canonicalize a configuration name.
Options:
-h, --help print this help, then exit
-t, --time-stamp print date of last modification, then exit
-v, --version print version number, then exit
Report bugs and patches to ."
version="\
GNU config.sub ($timestamp)
Copyright 1992-2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
help="
Try '$me --help' for more information."
# Parse command line
while test $# -gt 0 ; do
case $1 in
--time-stamp | --time* | -t )
echo "$timestamp" ; exit ;;
--version | -v )
echo "$version" ; exit ;;
--help | --h* | -h )
echo "$usage"; exit ;;
-- ) # Stop option processing
shift; break ;;
- ) # Use stdin as input.
break ;;
-* )
echo "$me: invalid option $1$help" >&2
exit 1 ;;
*local*)
# First pass through any local machine types.
echo "$1"
exit ;;
* )
break ;;
esac
done
case $# in
0) echo "$me: missing argument$help" >&2
exit 1;;
1) ;;
*) echo "$me: too many arguments$help" >&2
exit 1;;
esac
# Split fields of configuration type
saved_IFS=$IFS
IFS="-" read field1 field2 field3 field4 <&2
exit 1
;;
*-*-*-*)
basic_machine=$field1-$field2
basic_os=$field3-$field4
;;
*-*-*)
# Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
# parts
maybe_os=$field2-$field3
case $maybe_os in
cloudabi*-eabi* \
| kfreebsd*-gnu* \
| knetbsd*-gnu* \
| kopensolaris*-gnu* \
| linux-* \
| managarm-* \
| netbsd*-eabi* \
| netbsd*-gnu* \
| nto-qnx* \
| os2-emx* \
| rtmk-nova* \
| storm-chaos* \
| uclinux-gnu* \
| uclinux-uclibc* \
| windows-* )
basic_machine=$field1
basic_os=$maybe_os
;;
android-linux)
basic_machine=$field1-unknown
basic_os=linux-android
;;
*)
basic_machine=$field1-$field2
basic_os=$field3
;;
esac
;;
*-*)
case $field1-$field2 in
# Shorthands that happen to contain a single dash
convex-c[12] | convex-c3[248])
basic_machine=$field2-convex
basic_os=
;;
decstation-3100)
basic_machine=mips-dec
basic_os=
;;
*-*)
# Second component is usually, but not always the OS
case $field2 in
# Do not treat sunos as a manufacturer
sun*os*)
basic_machine=$field1
basic_os=$field2
;;
# Manufacturers
3100* \
| 32* \
| 3300* \
| 3600* \
| 7300* \
| acorn \
| altos* \
| apollo \
| apple \
| atari \
| att* \
| axis \
| be \
| bull \
| cbm \
| ccur \
| cisco \
| commodore \
| convergent* \
| convex* \
| cray \
| crds \
| dec* \
| delta* \
| dg \
| digital \
| dolphin \
| encore* \
| gould \
| harris \
| highlevel \
| hitachi* \
| hp \
| ibm* \
| intergraph \
| isi* \
| knuth \
| masscomp \
| microblaze* \
| mips* \
| motorola* \
| ncr* \
| news \
| next \
| ns \
| oki \
| omron* \
| pc533* \
| rebel \
| rom68k \
| rombug \
| semi \
| sequent* \
| siemens \
| sgi* \
| siemens \
| sim \
| sni \
| sony* \
| stratus \
| sun \
| sun[234]* \
| tektronix \
| tti* \
| ultra \
| unicom* \
| wec \
| winbond \
| wrs)
basic_machine=$field1-$field2
basic_os=
;;
zephyr*)
basic_machine=$field1-unknown
basic_os=$field2
;;
*)
basic_machine=$field1
basic_os=$field2
;;
esac
;;
esac
;;
*)
# Convert single-component short-hands not valid as part of
# multi-component configurations.
case $field1 in
386bsd)
basic_machine=i386-pc
basic_os=bsd
;;
a29khif)
basic_machine=a29k-amd
basic_os=udi
;;
adobe68k)
basic_machine=m68010-adobe
basic_os=scout
;;
alliant)
basic_machine=fx80-alliant
basic_os=
;;
altos | altos3068)
basic_machine=m68k-altos
basic_os=
;;
am29k)
basic_machine=a29k-none
basic_os=bsd
;;
amdahl)
basic_machine=580-amdahl
basic_os=sysv
;;
amiga)
basic_machine=m68k-unknown
basic_os=
;;
amigaos | amigados)
basic_machine=m68k-unknown
basic_os=amigaos
;;
amigaunix | amix)
basic_machine=m68k-unknown
basic_os=sysv4
;;
apollo68)
basic_machine=m68k-apollo
basic_os=sysv
;;
apollo68bsd)
basic_machine=m68k-apollo
basic_os=bsd
;;
aros)
basic_machine=i386-pc
basic_os=aros
;;
aux)
basic_machine=m68k-apple
basic_os=aux
;;
balance)
basic_machine=ns32k-sequent
basic_os=dynix
;;
blackfin)
basic_machine=bfin-unknown
basic_os=linux
;;
cegcc)
basic_machine=arm-unknown
basic_os=cegcc
;;
cray)
basic_machine=j90-cray
basic_os=unicos
;;
crds | unos)
basic_machine=m68k-crds
basic_os=
;;
da30)
basic_machine=m68k-da30
basic_os=
;;
decstation | pmax | pmin | dec3100 | decstatn)
basic_machine=mips-dec
basic_os=
;;
delta88)
basic_machine=m88k-motorola
basic_os=sysv3
;;
dicos)
basic_machine=i686-pc
basic_os=dicos
;;
djgpp)
basic_machine=i586-pc
basic_os=msdosdjgpp
;;
ebmon29k)
basic_machine=a29k-amd
basic_os=ebmon
;;
es1800 | OSE68k | ose68k | ose | OSE)
basic_machine=m68k-ericsson
basic_os=ose
;;
gmicro)
basic_machine=tron-gmicro
basic_os=sysv
;;
go32)
basic_machine=i386-pc
basic_os=go32
;;
h8300hms)
basic_machine=h8300-hitachi
basic_os=hms
;;
h8300xray)
basic_machine=h8300-hitachi
basic_os=xray
;;
h8500hms)
basic_machine=h8500-hitachi
basic_os=hms
;;
harris)
basic_machine=m88k-harris
basic_os=sysv3
;;
hp300 | hp300hpux)
basic_machine=m68k-hp
basic_os=hpux
;;
hp300bsd)
basic_machine=m68k-hp
basic_os=bsd
;;
hppaosf)
basic_machine=hppa1.1-hp
basic_os=osf
;;
hppro)
basic_machine=hppa1.1-hp
basic_os=proelf
;;
i386mach)
basic_machine=i386-mach
basic_os=mach
;;
isi68 | isi)
basic_machine=m68k-isi
basic_os=sysv
;;
m68knommu)
basic_machine=m68k-unknown
basic_os=linux
;;
magnum | m3230)
basic_machine=mips-mips
basic_os=sysv
;;
merlin)
basic_machine=ns32k-utek
basic_os=sysv
;;
mingw64)
basic_machine=x86_64-pc
basic_os=mingw64
;;
mingw32)
basic_machine=i686-pc
basic_os=mingw32
;;
mingw32ce)
basic_machine=arm-unknown
basic_os=mingw32ce
;;
monitor)
basic_machine=m68k-rom68k
basic_os=coff
;;
morphos)
basic_machine=powerpc-unknown
basic_os=morphos
;;
moxiebox)
basic_machine=moxie-unknown
basic_os=moxiebox
;;
msdos)
basic_machine=i386-pc
basic_os=msdos
;;
msys)
basic_machine=i686-pc
basic_os=msys
;;
mvs)
basic_machine=i370-ibm
basic_os=mvs
;;
nacl)
basic_machine=le32-unknown
basic_os=nacl
;;
ncr3000)
basic_machine=i486-ncr
basic_os=sysv4
;;
netbsd386)
basic_machine=i386-pc
basic_os=netbsd
;;
netwinder)
basic_machine=armv4l-rebel
basic_os=linux
;;
news | news700 | news800 | news900)
basic_machine=m68k-sony
basic_os=newsos
;;
news1000)
basic_machine=m68030-sony
basic_os=newsos
;;
necv70)
basic_machine=v70-nec
basic_os=sysv
;;
nh3000)
basic_machine=m68k-harris
basic_os=cxux
;;
nh[45]000)
basic_machine=m88k-harris
basic_os=cxux
;;
nindy960)
basic_machine=i960-intel
basic_os=nindy
;;
mon960)
basic_machine=i960-intel
basic_os=mon960
;;
nonstopux)
basic_machine=mips-compaq
basic_os=nonstopux
;;
os400)
basic_machine=powerpc-ibm
basic_os=os400
;;
OSE68000 | ose68000)
basic_machine=m68000-ericsson
basic_os=ose
;;
os68k)
basic_machine=m68k-none
basic_os=os68k
;;
paragon)
basic_machine=i860-intel
basic_os=osf
;;
parisc)
basic_machine=hppa-unknown
basic_os=linux
;;
psp)
basic_machine=mipsallegrexel-sony
basic_os=psp
;;
pw32)
basic_machine=i586-unknown
basic_os=pw32
;;
rdos | rdos64)
basic_machine=x86_64-pc
basic_os=rdos
;;
rdos32)
basic_machine=i386-pc
basic_os=rdos
;;
rom68k)
basic_machine=m68k-rom68k
basic_os=coff
;;
sa29200)
basic_machine=a29k-amd
basic_os=udi
;;
sei)
basic_machine=mips-sei
basic_os=seiux
;;
sequent)
basic_machine=i386-sequent
basic_os=
;;
sps7)
basic_machine=m68k-bull
basic_os=sysv2
;;
st2000)
basic_machine=m68k-tandem
basic_os=
;;
stratus)
basic_machine=i860-stratus
basic_os=sysv4
;;
sun2)
basic_machine=m68000-sun
basic_os=
;;
sun2os3)
basic_machine=m68000-sun
basic_os=sunos3
;;
sun2os4)
basic_machine=m68000-sun
basic_os=sunos4
;;
sun3)
basic_machine=m68k-sun
basic_os=
;;
sun3os3)
basic_machine=m68k-sun
basic_os=sunos3
;;
sun3os4)
basic_machine=m68k-sun
basic_os=sunos4
;;
sun4)
basic_machine=sparc-sun
basic_os=
;;
sun4os3)
basic_machine=sparc-sun
basic_os=sunos3
;;
sun4os4)
basic_machine=sparc-sun
basic_os=sunos4
;;
sun4sol2)
basic_machine=sparc-sun
basic_os=solaris2
;;
sun386 | sun386i | roadrunner)
basic_machine=i386-sun
basic_os=
;;
sv1)
basic_machine=sv1-cray
basic_os=unicos
;;
symmetry)
basic_machine=i386-sequent
basic_os=dynix
;;
t3e)
basic_machine=alphaev5-cray
basic_os=unicos
;;
t90)
basic_machine=t90-cray
basic_os=unicos
;;
toad1)
basic_machine=pdp10-xkl
basic_os=tops20
;;
tpf)
basic_machine=s390x-ibm
basic_os=tpf
;;
udi29k)
basic_machine=a29k-amd
basic_os=udi
;;
ultra3)
basic_machine=a29k-nyu
basic_os=sym1
;;
v810 | necv810)
basic_machine=v810-nec
basic_os=none
;;
vaxv)
basic_machine=vax-dec
basic_os=sysv
;;
vms)
basic_machine=vax-dec
basic_os=vms
;;
vsta)
basic_machine=i386-pc
basic_os=vsta
;;
vxworks960)
basic_machine=i960-wrs
basic_os=vxworks
;;
vxworks68)
basic_machine=m68k-wrs
basic_os=vxworks
;;
vxworks29k)
basic_machine=a29k-wrs
basic_os=vxworks
;;
xbox)
basic_machine=i686-pc
basic_os=mingw32
;;
ymp)
basic_machine=ymp-cray
basic_os=unicos
;;
*)
basic_machine=$1
basic_os=
;;
esac
;;
esac
# Decode 1-component or ad-hoc basic machines
case $basic_machine in
# Here we handle the default manufacturer of certain CPU types. It is in
# some cases the only manufacturer, in others, it is the most popular.
w89k)
cpu=hppa1.1
vendor=winbond
;;
op50n)
cpu=hppa1.1
vendor=oki
;;
op60c)
cpu=hppa1.1
vendor=oki
;;
ibm*)
cpu=i370
vendor=ibm
;;
orion105)
cpu=clipper
vendor=highlevel
;;
mac | mpw | mac-mpw)
cpu=m68k
vendor=apple
;;
pmac | pmac-mpw)
cpu=powerpc
vendor=apple
;;
# Recognize the various machine names and aliases which stand
# for a CPU type and a company and sometimes even an OS.
3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
cpu=m68000
vendor=att
;;
3b*)
cpu=we32k
vendor=att
;;
bluegene*)
cpu=powerpc
vendor=ibm
basic_os=cnk
;;
decsystem10* | dec10*)
cpu=pdp10
vendor=dec
basic_os=tops10
;;
decsystem20* | dec20*)
cpu=pdp10
vendor=dec
basic_os=tops20
;;
delta | 3300 | delta-motorola | 3300-motorola | motorola-delta | motorola-3300)
cpu=m68k
vendor=motorola
;;
# This used to be dpx2*, but that gets the RS6000-based
# DPX/20 and the x86-based DPX/2-100 wrong. See
# https://oldskool.silicium.org/stations/bull_dpx20.htm
# https://www.feb-patrimoine.com/english/bull_dpx2.htm
# https://www.feb-patrimoine.com/english/unix_and_bull.htm
dpx2 | dpx2[23]00 | dpx2[23]xx)
cpu=m68k
vendor=bull
;;
dpx2100 | dpx21xx)
cpu=i386
vendor=bull
;;
dpx20)
cpu=rs6000
vendor=bull
;;
encore | umax | mmax)
cpu=ns32k
vendor=encore
;;
elxsi)
cpu=elxsi
vendor=elxsi
basic_os=${basic_os:-bsd}
;;
fx2800)
cpu=i860
vendor=alliant
;;
genix)
cpu=ns32k
vendor=ns
;;
h3050r* | hiux*)
cpu=hppa1.1
vendor=hitachi
basic_os=hiuxwe2
;;
hp3k9[0-9][0-9] | hp9[0-9][0-9])
cpu=hppa1.0
vendor=hp
;;
hp9k2[0-9][0-9] | hp9k31[0-9])
cpu=m68000
vendor=hp
;;
hp9k3[2-9][0-9])
cpu=m68k
vendor=hp
;;
hp9k6[0-9][0-9] | hp6[0-9][0-9])
cpu=hppa1.0
vendor=hp
;;
hp9k7[0-79][0-9] | hp7[0-79][0-9])
cpu=hppa1.1
vendor=hp
;;
hp9k78[0-9] | hp78[0-9])
# FIXME: really hppa2.0-hp
cpu=hppa1.1
vendor=hp
;;
hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
# FIXME: really hppa2.0-hp
cpu=hppa1.1
vendor=hp
;;
hp9k8[0-9][13679] | hp8[0-9][13679])
cpu=hppa1.1
vendor=hp
;;
hp9k8[0-9][0-9] | hp8[0-9][0-9])
cpu=hppa1.0
vendor=hp
;;
i*86v32)
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv32
;;
i*86v4*)
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv4
;;
i*86v)
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=sysv
;;
i*86sol2)
cpu=`echo "$1" | sed -e 's/86.*/86/'`
vendor=pc
basic_os=solaris2
;;
j90 | j90-cray)
cpu=j90
vendor=cray
basic_os=${basic_os:-unicos}
;;
iris | iris4d)
cpu=mips
vendor=sgi
case $basic_os in
irix*)
;;
*)
basic_os=irix4
;;
esac
;;
miniframe)
cpu=m68000
vendor=convergent
;;
*mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
cpu=m68k
vendor=atari
basic_os=mint
;;
news-3600 | risc-news)
cpu=mips
vendor=sony
basic_os=newsos
;;
next | m*-next)
cpu=m68k
vendor=next
;;
np1)
cpu=np1
vendor=gould
;;
op50n-* | op60c-*)
cpu=hppa1.1
vendor=oki
basic_os=proelf
;;
pa-hitachi)
cpu=hppa1.1
vendor=hitachi
basic_os=hiuxwe2
;;
pbd)
cpu=sparc
vendor=tti
;;
pbb)
cpu=m68k
vendor=tti
;;
pc532)
cpu=ns32k
vendor=pc532
;;
pn)
cpu=pn
vendor=gould
;;
power)
cpu=power
vendor=ibm
;;
ps2)
cpu=i386
vendor=ibm
;;
rm[46]00)
cpu=mips
vendor=siemens
;;
rtpc | rtpc-*)
cpu=romp
vendor=ibm
;;
sde)
cpu=mipsisa32
vendor=sde
basic_os=${basic_os:-elf}
;;
simso-wrs)
cpu=sparclite
vendor=wrs
basic_os=vxworks
;;
tower | tower-32)
cpu=m68k
vendor=ncr
;;
vpp*|vx|vx-*)
cpu=f301
vendor=fujitsu
;;
w65)
cpu=w65
vendor=wdc
;;
w89k-*)
cpu=hppa1.1
vendor=winbond
basic_os=proelf
;;
none)
cpu=none
vendor=none
;;
leon|leon[3-9])
cpu=sparc
vendor=$basic_machine
;;
leon-*|leon[3-9]-*)
cpu=sparc
vendor=`echo "$basic_machine" | sed 's/-.*//'`
;;
*-*)
saved_IFS=$IFS
IFS="-" read cpu vendor <&2
exit 1
;;
esac
;;
esac
# Here we canonicalize certain aliases for manufacturers.
case $vendor in
digital*)
vendor=dec
;;
commodore*)
vendor=cbm
;;
*)
;;
esac
# Decode manufacturer-specific aliases for certain operating systems.
if test x"$basic_os" != x
then
# First recognize some ad-hoc cases, or perhaps split kernel-os, or else just
# set os.
obj=
case $basic_os in
gnu/linux*)
kernel=linux
os=`echo "$basic_os" | sed -e 's|gnu/linux|gnu|'`
;;
os2-emx)
kernel=os2
os=`echo "$basic_os" | sed -e 's|os2-emx|emx|'`
;;
nto-qnx*)
kernel=nto
os=`echo "$basic_os" | sed -e 's|nto-qnx|qnx|'`
;;
*-*)
saved_IFS=$IFS
IFS="-" read kernel os <&2
fi
;;
*)
echo "Invalid configuration '$1': OS '$os' not recognized" 1>&2
exit 1
;;
esac
case $obj in
aout* | coff* | elf* | pe*)
;;
'')
# empty is fine
;;
*)
echo "Invalid configuration '$1': Machine code format '$obj' not recognized" 1>&2
exit 1
;;
esac
# Here we handle the constraint that a (synthetic) cpu and os are
# valid only in combination with each other and nowhere else.
case $cpu-$os in
# The "javascript-unknown-ghcjs" triple is used by GHC; we
# accept it here in order to tolerate that, but reject any
# variations.
javascript-ghcjs)
;;
javascript-* | *-ghcjs)
echo "Invalid configuration '$1': cpu '$cpu' is not valid with os '$os$obj'" 1>&2
exit 1
;;
esac
# As a final step for OS-related things, validate the OS-kernel combination
# (given a valid OS), if there is a kernel.
case $kernel-$os-$obj in
linux-gnu*- | linux-android*- | linux-dietlibc*- | linux-llvm*- \
| linux-mlibc*- | linux-musl*- | linux-newlib*- \
| linux-relibc*- | linux-uclibc*- | linux-ohos*- )
;;
uclinux-uclibc*- | uclinux-gnu*- )
;;
managarm-mlibc*- | managarm-kernel*- )
;;
windows*-msvc*-)
;;
-dietlibc*- | -llvm*- | -mlibc*- | -musl*- | -newlib*- | -relibc*- \
| -uclibc*- )
# These are just libc implementations, not actual OSes, and thus
# require a kernel.
echo "Invalid configuration '$1': libc '$os' needs explicit kernel." 1>&2
exit 1
;;
-kernel*- )
echo "Invalid configuration '$1': '$os' needs explicit kernel." 1>&2
exit 1
;;
*-kernel*- )
echo "Invalid configuration '$1': '$kernel' does not support '$os'." 1>&2
exit 1
;;
*-msvc*- )
echo "Invalid configuration '$1': '$os' needs 'windows'." 1>&2
exit 1
;;
kfreebsd*-gnu*- | knetbsd*-gnu*- | netbsd*-gnu*- | kopensolaris*-gnu*-)
;;
vxworks-simlinux- | vxworks-simwindows- | vxworks-spe-)
;;
nto-qnx*-)
;;
os2-emx-)
;;
rtmk-nova-)
;;
*-eabi*- | *-gnueabi*-)
;;
none--*)
# None (no kernel, i.e. freestanding / bare metal),
# can be paired with an machine code file format
;;
-*-)
# Blank kernel with real OS is always fine.
;;
--*)
# Blank kernel and OS with real machine code file format is always fine.
;;
*-*-*)
echo "Invalid configuration '$1': Kernel '$kernel' not known to work with OS '$os'." 1>&2
exit 1
;;
esac
# Here we handle the case where we know the os, and the CPU type, but not the
# manufacturer. We pick the logical manufacturer.
case $vendor in
unknown)
case $cpu-$os in
*-riscix*)
vendor=acorn
;;
*-sunos* | *-solaris*)
vendor=sun
;;
*-cnk* | *-aix*)
vendor=ibm
;;
*-beos*)
vendor=be
;;
*-hpux*)
vendor=hp
;;
*-mpeix*)
vendor=hp
;;
*-hiux*)
vendor=hitachi
;;
*-unos*)
vendor=crds
;;
*-dgux*)
vendor=dg
;;
*-luna*)
vendor=omron
;;
*-genix*)
vendor=ns
;;
*-clix*)
vendor=intergraph
;;
*-mvs* | *-opened*)
vendor=ibm
;;
*-os400*)
vendor=ibm
;;
s390-* | s390x-*)
vendor=ibm
;;
*-ptx*)
vendor=sequent
;;
*-tpf*)
vendor=ibm
;;
*-vxsim* | *-vxworks* | *-windiss*)
vendor=wrs
;;
*-aux*)
vendor=apple
;;
*-hms*)
vendor=hitachi
;;
*-mpw* | *-macos*)
vendor=apple
;;
*-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
vendor=atari
;;
*-vos*)
vendor=stratus
;;
esac
;;
esac
echo "$cpu-$vendor${kernel:+-$kernel}${os:+-$os}${obj:+-$obj}"
exit
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "timestamp='"
# time-stamp-format: "%:y-%02m-%02d"
# time-stamp-end: "'"
# End:
mdk-1.3.1/AUTHORS 0000644 0001750 0001750 00000000754 12636565126 007042 Authors of GNU MDK.
See also the files THANKS and ChangeLog.
Jose A. Ortega Ruiz designed and implemented mdk.
Pieter E. J. Pareit designed, implemented and documented
mixal-mode.el, and fixed bugs in other mdk code.
Philip E. King designed and implemented mixvm.el.
Michael Scholz wrote the German translation po/de.po.
Sergey Poznyakoff provided patches to mixlib/mix_scanner.l improving
MIXAL compliance.
Sergey Litvin implemented SLB, SRB, JAE, JAO, JXE, JXE instructions in
mixvm.
mdk-1.3.1/mixgtk/ 0000775 0001750 0001750 00000000000 15065042311 007332 5 mdk-1.3.1/mixgtk/mixgtk_input.h 0000644 0001750 0001750 00000003066 12112755472 012161 /* -*-c-*- ---------------- mixgtk_input.h :
* Declaration of functions for user input
* ------------------------------------------------------------------
* Last change: Time-stamp: <01/03/12 23:35:14 jose>
* ------------------------------------------------------------------
* Copyright (C) 2001, 2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef MIXGTK_INPUT_H
#define MIXGTK_INPUT_H
#include
/* callback function type */
typedef void (*input_callback_t)(mix_word_t result, gpointer data);
/* init */
extern void
mixgtk_input_init (void);
/* get a word */
extern void
mixgtk_input_word (const gchar *message, mix_word_t def,
input_callback_t cb, gpointer data);
/* get a short */
extern void
mixgtk_input_short (const gchar *message, mix_short_t def,
input_callback_t cb, gpointer data );
#endif /* MIXGTK_INPUT_H */
mdk-1.3.1/mixgtk/mixgtk_mixvm.c 0000644 0001750 0001750 00000033370 13743201230 012143 /* -*-c-*- -------------- mixgtk_mixvm.c :
* Implementation of the functions declared in mixgtk_mixvm.h
* ------------------------------------------------------------------
* Copyright (C) 2001, 2002, 2004, 2006, 2007, 2008, 2019 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include
#include
#include "mixgtk_widgets.h"
#include "mixgtk_fontsel.h"
#include "mixgtk_mixvm.h"
#include "mixgtk_cmd_dispatcher.h"
#include "mixgtk_input.h"
/* Local variables */
#define REGISTER_NO_ (MIXGTK_WIDGET_rI6 - MIXGTK_WIDGET_rA + 1)
static GtkEntry *reg_entries_[REGISTER_NO_];
static GtkEntry *loc_entry_;
static GtkWidget *goto_ = NULL;
static GtkEntry *goto_entry_ = NULL;
static GtkToggleButton *over_button_;
static GtkToggleButton *cmp_buttons_[3];
static GtkTreeView *memory_;
static GtkListStore *mem_store_;
static GtkLabel *laptime_;
static GtkLabel *progtime_;
static GtkLabel *uptime_;
static mix_vm_t *vm_;
#define HAVE_OLD_GTK !GTK_CHECK_VERSION(2, 12, 0)
#if HAVE_OLD_GTK
static GtkTooltips *tips_ = NULL;
#endif
/* Static function prototypes */
static void init_goto_ (void);
static void update_register_ (mixgtk_widget_id_t reg);
static gboolean init_mem_ (void);
enum {
MEM_ADDRESS_COL,
MEM_CONTENTS_COL,
MEM_COL_NO
};
/* initialise the mixvm widgets */
gboolean
mixgtk_mixvm_init (mix_vm_t *vm)
{
int k;
g_assert (vm != NULL);
vm_ = vm;
#if HAVE_OLD_GTK
if (!tips_) tips_ = gtk_tooltips_new ();
#endif
for (k = 0; k < REGISTER_NO_; ++k)
{
reg_entries_[k] =
GTK_ENTRY (mixgtk_widget_factory_get(MIXGTK_MIXVM_DIALOG,
MIXGTK_WIDGET_rA + k));
g_assert (reg_entries_[k] != NULL);
mixgtk_fontsel_set_font (MIX_FONT_MIXVM,
GTK_WIDGET (reg_entries_[k]));
}
loc_entry_ =
GTK_ENTRY (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG,
MIXGTK_WIDGET_LOC));
g_assert (loc_entry_ != NULL);
mixgtk_fontsel_set_font (MIX_FONT_MIXVM, GTK_WIDGET (loc_entry_));
uptime_ =
GTK_LABEL (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG,
MIXGTK_WIDGET_UPTIME));
g_assert (uptime_ != NULL);
progtime_ =
GTK_LABEL (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG,
MIXGTK_WIDGET_PROGTIME));
g_assert (progtime_ != NULL);
laptime_ =
GTK_LABEL (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG,
MIXGTK_WIDGET_LAPTIME));
g_assert (laptime_ != NULL);
over_button_ =
GTK_TOGGLE_BUTTON
(mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG, MIXGTK_WIDGET_OVER));
g_assert (over_button_ != NULL);
for (k = 0; k < 3; ++k)
{
cmp_buttons_[k] = GTK_TOGGLE_BUTTON
(mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG,
MIXGTK_WIDGET_CMP_L +k));
g_assert (cmp_buttons_[k] != NULL);
}
init_mem_ ();
return TRUE;
}
static GtkWidget **
text_widgets_ (gint *n)
{
static GtkWidget *w[REGISTER_NO_ + 2] = { NULL};
if (w[0] == NULL)
{
gint k;
w[0] = GTK_WIDGET (loc_entry_);
w[1] = GTK_WIDGET (memory_);
for (k = 0; k < REGISTER_NO_; ++k)
w[k + 2] = GTK_WIDGET (reg_entries_[k]);
};
if (n) *n = REGISTER_NO_ + 2;
return w;
}
void
mixgtk_mixvm_update_fonts (void)
{
gint k, n = 0;
GtkWidget **w = text_widgets_ (&n);
for (k = 0; k < n; ++k)
mixgtk_fontsel_set_font (MIX_FONT_MIXVM, w[k]);
}
/* update register widgets */
void
mixgtk_mixvm_update_registers (void)
{
gint k;
for (k = MIXGTK_WIDGET_rA; k <= MIXGTK_WIDGET_rI6; ++k)
update_register_ (k);
}
/* update the overflow toggle */
void
mixgtk_mixvm_update_over_toggle (void)
{
g_assert (over_button_);
gtk_toggle_button_set_active (over_button_,
mix_vm_get_overflow (vm_));
}
/* update the comparison flag */
void
mixgtk_mixvm_update_cmp (void)
{
gint toggle = mix_vm_get_cmpflag (vm_);
gtk_toggle_button_set_active (cmp_buttons_[toggle], TRUE);
}
/* update the memory cells */
void
mixgtk_mixvm_update_cells (void)
{
static gchar BUFFER[20];
GtkTreeIter iter;
gboolean valid =
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (mem_store_), &iter);
gint k = 0;
while (valid)
{
mix_word_print_to_buffer (mix_vm_get_addr_contents (vm_, k++), BUFFER);
gtk_list_store_set (mem_store_, &iter, MEM_CONTENTS_COL, BUFFER, -1);
valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (mem_store_), &iter);
}
}
void
mixgtk_mixvm_update_cells_to_address (gint address)
{
GtkTreePath *path = gtk_tree_path_new_from_indices (address, -1);
if (address >= MIX_VM_CELL_NO) return;
gtk_tree_view_scroll_to_cell (memory_, path, NULL, TRUE, 0, 0);
gtk_tree_path_free (path);
}
/* update the loc pointer */
void
mixgtk_mixvm_update_loc (void)
{
enum {SIZE = 10 };
static gchar BUFFER[SIZE];
mix_short_t locval;
g_assert (loc_entry_);
locval = mix_vm_get_prog_count (vm_);
g_snprintf (BUFFER, SIZE, "%04d", mix_short_magnitude (locval));
gtk_entry_set_text (loc_entry_, BUFFER);
}
/* update times */
void
mixgtk_mixvm_update_times (void)
{
enum {SIZE = 20 };
static gchar BUFFER[SIZE];
gint uptime, progtime, laptime;
g_assert (uptime_ && progtime_ && laptime_);
mixgtk_cmd_dispatcher_get_times (&uptime, &progtime, &laptime);
g_snprintf (BUFFER, SIZE, "%d", uptime);
gtk_label_set_text (uptime_, BUFFER);
g_snprintf (BUFFER, SIZE, "%d", progtime);
gtk_label_set_text (progtime_, BUFFER);
g_snprintf (BUFFER, SIZE, "%d", laptime);
gtk_label_set_text (laptime_, BUFFER);
}
/* update all mixvm widgets */
void
mixgtk_mixvm_update_vm_widgets (void)
{
mixgtk_mixvm_update_registers ();
mixgtk_mixvm_update_loc ();
mixgtk_mixvm_update_over_toggle ();
mixgtk_mixvm_update_cmp ();
mixgtk_mixvm_update_cells ();
mixgtk_mixvm_update_times ();
}
/* update cmp flag */
static gboolean
button_active_ (GtkWidget *widget)
{
return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
}
void
on_cmp_e_toggled (GtkWidget *widget, gpointer data)
{
if (button_active_ (widget))
mix_vm_set_cmpflag (vm_, mix_EQ);
}
void
on_cmp_l_toggled (GtkWidget *widget, gpointer data)
{
if (button_active_ (widget))
mix_vm_set_cmpflag (vm_, mix_LESS);
}
void
on_cmp_g_toggled (GtkWidget *widget, gpointer data)
{
if (button_active_ (widget))
mix_vm_set_cmpflag (vm_, mix_GREAT);
}
void
on_overflow_toggled (GtkWidget *widget, gpointer data)
{
mix_vm_set_overflow (vm_, button_active_ (widget));
}
void
on_loc_arrow_clicked (GtkWidget *widget, gpointer data)
{
gint address = mix_short_magnitude (mix_vm_get_prog_count (vm_));
mixgtk_mixvm_update_cells_to_address (address);
}
static void
register_AX_ (mix_word_t w, gpointer reg)
{
gint k = GPOINTER_TO_INT (reg);
if (k == 0)
mix_vm_set_rA (vm_, w);
else
mix_vm_set_rX (vm_, w);
update_register_ (MIXGTK_WIDGET_rA + k);
}
static void
register_j_ (mix_word_t w, gpointer data)
{
if (mix_word_is_negative (w)) mix_word_reverse_sign (w);
mix_vm_set_rJ (vm_, mix_word_to_short_fast (w));
update_register_ (MIXGTK_WIDGET_rJ);
}
static void
register_i_ (mix_word_t w, gpointer reg)
{
mix_vm_set_rI (vm_, GPOINTER_TO_INT (reg), mix_word_to_short_fast (w));
update_register_ (MIXGTK_WIDGET_rI1 - 1 + GPOINTER_TO_INT (reg));
}
gboolean
on_register_click (GtkWidget *w, GdkEvent *e, gpointer data)
{
enum {SIZE = 20};
static gchar BUFFER[SIZE];
gint k;
if (w == GTK_WIDGET (reg_entries_[0]))
mixgtk_input_word (_("Register A"), mix_vm_get_rA (vm_),
register_AX_, GINT_TO_POINTER (0));
else if (w == GTK_WIDGET (reg_entries_[1]))
mixgtk_input_word (_("Register X"), mix_vm_get_rX (vm_),
register_AX_, GINT_TO_POINTER(1));
else if (w == GTK_WIDGET (reg_entries_[2]))
mixgtk_input_short (_("Register J"), mix_vm_get_rJ (vm_),
register_j_, NULL);
else for (k = 1; k < 7; ++k)
{
if (w == GTK_WIDGET (reg_entries_[2 + k]))
{
g_snprintf (BUFFER, SIZE, _("Register I%d"), k);
mixgtk_input_short (BUFFER, mix_vm_get_rI (vm_, k),
register_i_, GINT_TO_POINTER (k));
break;
}
}
return TRUE;
}
static void
mem_cell_ (mix_word_t w, gpointer a)
{
mix_short_t addr = mix_short_new (GPOINTER_TO_INT (a));
mix_vm_set_addr_contents (vm_, addr, w);
mixgtk_mixvm_update_cells ();
}
void
on_mix_font_activate (void)
{
gint n;
GtkWidget **w = text_widgets_ (&n);
mixgtk_fontsel_query_font (MIX_FONT_MIXVM, w, n);
}
/* static functions */
static void
init_goto_ (void)
{
goto_ = mixgtk_widget_factory_get_dialog (MIXGTK_GOTO_DIALOG);
g_assert (goto_ != NULL);
goto_entry_ =
GTK_ENTRY (mixgtk_widget_factory_get (MIXGTK_GOTO_DIALOG,
MIXGTK_WIDGET_GOTO_ENTRY));
g_assert (goto_entry_ != NULL);
}
static void
update_register_ (mixgtk_widget_id_t reg)
{
static gchar BUFFER[20];
mix_word_t tipval = MIX_WORD_ZERO;
switch (reg)
{
case MIXGTK_WIDGET_rA:
tipval = mix_vm_get_rA (vm_);
mix_word_print_to_buffer (tipval, BUFFER);
break;
case MIXGTK_WIDGET_rX:
tipval = mix_vm_get_rX (vm_);
mix_word_print_to_buffer (tipval, BUFFER);
break;
case MIXGTK_WIDGET_rJ:
tipval = mix_short_to_word_fast (mix_vm_get_rJ (vm_));
mix_short_print_to_buffer (mix_vm_get_rJ (vm_), BUFFER);
break;
case MIXGTK_WIDGET_rI1:
case MIXGTK_WIDGET_rI2:
case MIXGTK_WIDGET_rI3:
case MIXGTK_WIDGET_rI4:
case MIXGTK_WIDGET_rI5:
case MIXGTK_WIDGET_rI6:
{
gint k = reg - MIXGTK_WIDGET_rI1 + 1;
tipval = mix_short_to_word_fast (mix_vm_get_rI (vm_, k));
mix_short_print_to_buffer (mix_vm_get_rI (vm_, k), BUFFER);
}
break;
default:
g_assert_not_reached ();
}
gtk_entry_set_text (reg_entries_[reg - MIXGTK_WIDGET_rA], BUFFER);
g_snprintf (BUFFER, 20, "%s%ld", mix_word_is_negative (tipval)? "-" : "",
mix_word_magnitude (tipval));
#if HAVE_OLD_GTK
gtk_tooltips_set_tip (tips_,
GTK_WIDGET (reg_entries_[reg - MIXGTK_WIDGET_rA]),
BUFFER, NULL);
#else
gtk_widget_set_tooltip_text (
GTK_WIDGET (reg_entries_[reg - MIXGTK_WIDGET_rA]), BUFFER);
#endif
}
static void
cells_clicked_ (GtkTreeViewColumn* col, gpointer data)
{
if (!goto_) init_goto_ ();
if (gtk_dialog_run (GTK_DIALOG (goto_)) == GTK_RESPONSE_OK)
{
const gchar *txt = gtk_entry_get_text (goto_entry_);
mix_short_t addr = mix_short_new (atoi (txt));
if (addr < MIX_VM_CELL_NO)
mixgtk_mixvm_update_cells_to_address (addr);
}
gtk_widget_hide (goto_);
}
static gboolean
cont_clicked_ (GtkWidget *w, GdkEvent *event, gpointer data)
{
enum {SIZE = 30};
static gchar BUFFER[SIZE];
if (event && event->type == GDK_BUTTON_PRESS)
{
GtkTreeIter iter;
GtkTreeModel *model;
GtkTreeSelection *selection;
selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (memory_));
if (gtk_tree_selection_get_selected (selection, &model, &iter))
{
gint addr;
gtk_tree_model_get (model, &iter, MEM_ADDRESS_COL, &addr, -1);
g_snprintf (BUFFER, SIZE, _("Memory cell no. %d"), addr);
mixgtk_input_word
(BUFFER,
mix_vm_get_addr_contents (vm_, mix_short_new (addr)),
mem_cell_, GINT_TO_POINTER (addr));
}
}
return FALSE;
}
static gboolean
init_mem_ (void)
{
gint k;
GtkTreeIter iter;
GtkCellRenderer *renderer;
GtkTreeViewColumn *col;
/* model */
mem_store_ = gtk_list_store_new (MEM_COL_NO, G_TYPE_INT, G_TYPE_STRING);
g_assert (mem_store_);
for (k = 0; k< MIX_VM_CELL_NO; ++k)
{
gtk_list_store_append (mem_store_, &iter);
gtk_list_store_set (mem_store_, &iter,
MEM_ADDRESS_COL, k,
MEM_CONTENTS_COL, "+ 00 00 00 00 00",
-1);
}
/* view */
renderer = gtk_cell_renderer_text_new ();
memory_ =
GTK_TREE_VIEW (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG,
MIXGTK_WIDGET_CELLS));
g_assert (memory_);
g_assert (renderer);
gtk_tree_view_set_model (memory_, GTK_TREE_MODEL (mem_store_));
gtk_tree_view_set_headers_clickable (memory_, TRUE);
g_object_unref (G_OBJECT (mem_store_));
col = gtk_tree_view_column_new_with_attributes ("Address", renderer,
"text", 0, NULL);
gtk_tree_view_column_set_clickable (col, TRUE);
g_signal_connect (G_OBJECT (col), "clicked",
G_CALLBACK (cells_clicked_), NULL);
gtk_tree_view_append_column (memory_, col);
col = gtk_tree_view_column_new_with_attributes ("Contents", renderer,
"text", 1, NULL);
gtk_tree_view_column_set_clickable (col, TRUE);
g_signal_connect (G_OBJECT (col), "clicked",
G_CALLBACK (cont_clicked_), NULL);
gtk_tree_view_append_column (memory_, col);
g_signal_connect_after (G_OBJECT (memory_), "event-after",
G_CALLBACK (cont_clicked_), NULL);
mixgtk_fontsel_set_font (MIX_FONT_MIXVM, GTK_WIDGET (memory_));
return TRUE;
}
mdk-1.3.1/mixgtk/mixgtk_widgets.c 0000644 0001750 0001750 00000006423 13743201230 012450 /* -*-c-*- -------------- mixgtk_widgets.c :
* Implementation of the functions declared in mixgtk_widgets.h
* ------------------------------------------------------------------
* Copyright (C) 2001, 2004, 2006, 2007, 2014, 2019, 2020 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include
#include
#include "mixgtk_config.h"
#include "mixgtk_widgets.h"
/* dialog names */
static const gchar * dnames_[] = {
"main_window",
"mixvm_window",
"mixal_window",
"devices_window",
"word_dialog",
"about_dialog",
"goto_dialog",
"fontsel_dialog",
"devform_dialog",
"external_dialog",
"symbols_dialog",
"input_dialog",
"devdir_dialog"
};
#define DLG_NO_ (sizeof (dnames_) / sizeof(dnames_[0]))
/* widget names */
static const gchar *names_[] = {
"main_statusbar",
"attach_button",
"detach_button",
"main_notebook",
"mixvm_widget",
"mixvm_container",
"command_prompt",
"command_log",
"dev_container",
"mixal_container",
"mixal_statusbar",
"rA_entry",
"rX_entry",
"rJ_entry",
"rI1_entry",
"rI2_entry",
"rI3_entry",
"rI4_entry",
"rI5_entry",
"rI6_entry",
"lesser_radio",
"equal_radio",
"greater_radio",
"over_toggle",
"memory_cells",
"elapsed_label",
"program_label",
"uptime_label",
"devices_container",
"loc_entry",
"goto_entry",
NULL
};
#define WIDGET_NO_ (sizeof (names_) / sizeof (names_[0]))
/* the glade specs */
static GtkBuilder *builder_ = NULL;
/* the xml file name */
static const gchar *file_ = NULL;
/* create a new factory from an xml glade file */
gboolean
mixgtk_widget_factory_init (void)
{
if (!file_)
{
const gchar *glade_file = GLADE_FILE;
if (access (glade_file, R_OK)) {
if (access (LOCAL_GLADE_FILE, R_OK)) return FALSE;
glade_file = LOCAL_GLADE_FILE;
}
file_ = g_strdup (glade_file);
builder_ = gtk_builder_new_from_file (file_);
g_assert (builder_);
gtk_builder_connect_signals (builder_, NULL);
}
return TRUE;
}
/* get a widget */
GtkWidget *
mixgtk_widget_factory_get (mixgtk_dialog_id_t dlg, mixgtk_widget_id_t widget)
{
g_assert ((long)widget < WIDGET_NO_);
return mixgtk_widget_factory_get_by_name (names_[widget]);
}
GtkWidget *
mixgtk_widget_factory_get_dialog (mixgtk_dialog_id_t dlg)
{
g_assert (dlg < DLG_NO_);
return GTK_WIDGET (gtk_builder_get_object (builder_, dnames_[dlg]));
}
GtkWidget *
mixgtk_widget_factory_get_by_name (const gchar *name)
{
g_assert (name != NULL);
GtkWidget *w = GTK_WIDGET (gtk_builder_get_object (builder_, name));
if (!w) g_warning ("Widget '%s' not found", name);
return w;
}
mdk-1.3.1/mixgtk/mixgtk_mixal.h 0000644 0001750 0001750 00000003251 12112755472 012130 /* -*-c-*- ---------------- mixgtk_mixal.h :
* Declarations for functions displaying the mixal source file
* ------------------------------------------------------------------
* Copyright (C) 2001, 2004, 2006, 2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef MIXGTK_MIXAL_H
#define MIXGTK_MIXAL_H
#include
#include
#include "mixgtk_widgets.h"
/* initialise the mixal widget */
extern GtkWidget *
mixgtk_mixal_init (mix_vm_t *vm);
extern void
mixgtk_mixal_reparent (GtkStatusbar *stat);
/* load the corresponding mixal file */
extern void
mixgtk_mixal_load_file (void);
/* update the widget */
extern void
mixgtk_mixal_update (void);
extern void
mixgtk_mixal_update_fonts (void);
extern void
mixgtk_mixal_pop_status (void);
/* breakpoints */
extern void
mixgtk_mixal_update_bp_at_address (guint addr);
extern void
mixgtk_mixal_update_bp_at_line (guint line);
extern void
mixgtk_mixal_update_bp_all (void);
#endif /* MIXGTK_MIXAL_H */
mdk-1.3.1/mixgtk/mixgtk_input.c 0000644 0001750 0001750 00000014023 13743201230 012134 /* -*-c-*- -------------- mixgtk_input.c :
* Implementation of the functions declared in mixgtk_input.h
* ------------------------------------------------------------------
* Copyright (C) 2001, 2002, 2004, 2006, 2007, 2019, 2020 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include
#include
#include
#include "mixgtk_widgets.h"
#include "mixgtk_input.h"
enum {
MSG_, SIGN_, B1_, B2_, B3_, B4_, B5_, DEC_, RESET_, OK_, SIZE_
};
static const gchar *WGT_NAMES_[SIZE_] = {
"word_label", "word_sign", "word_b1", "word_b2", "word_b3",
"word_b4", "word_b5", "word_decimal", "word_reset", "word_ok"
};
static GtkDialog *dialog_ = NULL;
static GtkWidget *childs_[SIZE_];
static input_callback_t callback_;
static gpointer data_;
static void init_dialog_ (void);
static void set_word_ (mix_word_t word);
/* init */
void
mixgtk_input_init (void)
{
dialog_ = NULL;
}
/* get a word */
void
mixgtk_input_word (const gchar *message, mix_word_t def,
input_callback_t cb, gpointer data)
{
if (!dialog_) init_dialog_ ();
gtk_label_set_text (GTK_LABEL (childs_[MSG_]), message);
set_word_ (def);
callback_ = cb;
data_ = data;
gtk_widget_show (childs_[B1_]);
gtk_widget_show (childs_[B2_]);
gtk_widget_show (childs_[B3_]);
gtk_widget_show (GTK_WIDGET (dialog_));
}
/* get a short */
void
mixgtk_input_short (const gchar *message, mix_short_t def,
input_callback_t cb, gpointer data)
{
if (!dialog_) init_dialog_ ();
gtk_label_set_text (GTK_LABEL (childs_[MSG_]), message);
set_word_ (mix_word_to_short_fast (def));
callback_ = cb;
data_ = data;
gtk_widget_show (GTK_WIDGET (dialog_));
gtk_widget_hide (childs_[B1_]);
gtk_widget_hide (childs_[B2_]);
gtk_widget_hide (childs_[B3_]);
}
#include
/* dec and bytes input handler */
void
on_word_dec_changed (GtkEditable *dec, gpointer *data)
{
gchar *txt = gtk_editable_get_chars (dec, 0, -1);
if (strlen (txt) > 0)
{
gint val = atoi (txt);
set_word_ (mix_word_new (val));
}
g_free (txt);
}
void
on_word_byte_changed (GtkEditable *byte, gpointer *data)
{
gchar *txt = gtk_editable_get_chars (byte, 0, 2);
if (strlen (txt) > 0)
{
mix_byte_t bytes[5];
gint k;
const gchar *s;
mix_word_t w;
for (k = 0; k < 5; ++k)
{
const gchar *text = gtk_entry_get_text (GTK_ENTRY (childs_[B1_ + k]));
bytes[k] = mix_byte_new (atoi (text));
}
w = mix_bytes_to_word (bytes, 5);
s = gtk_entry_get_text (GTK_ENTRY (childs_[SIGN_]));
if (s && s[0] == '-') mix_word_reverse_sign (w);
set_word_ (w);
}
g_free (txt);
}
void
on_word_sign_changed (GtkEditable *sign, gpointer *data)
{
gchar *txt = gtk_editable_get_chars (sign, 0, 1);
if (strlen (txt) > 0)
{
gint pos = 0;
mix_word_t w =
mix_word_new (atoi (gtk_entry_get_text (GTK_ENTRY (childs_[DEC_]))));
g_signal_handlers_block_by_func (sign,
on_word_sign_changed, data);
if (txt[0] != '+' && txt[0] != '-') txt[0] = '+';
gtk_editable_delete_text (sign, 0, 1);
gtk_editable_insert_text (sign, txt, 1, &pos);
g_signal_handlers_unblock_by_func (sign,
on_word_sign_changed, data);
set_word_ (txt[0] == '-' ? mix_word_negative (w) : w);
}
g_free (txt);
}
void
on_word_ok_clicked (GtkWidget *widget, gpointer *data)
{
const gchar *text = gtk_entry_get_text (GTK_ENTRY (childs_[DEC_]));
mix_word_t w = mix_word_new (atoi (text));
if (w == MIX_WORD_ZERO)
{
const gchar *sign = gtk_entry_get_text (GTK_ENTRY (childs_[SIGN_]));
if (sign && sign[0] == '-') mix_word_reverse_sign (w);
}
callback_ (w, data_);
gtk_widget_hide (GTK_WIDGET (dialog_));
}
void
on_word_cancel_clicked (GtkWidget *widget, gpointer *data)
{
gtk_widget_hide (GTK_WIDGET (dialog_));
}
void
on_word_reset_clicked (GtkWidget *w, gpointer *data)
{
set_word_ (MIX_WORD_ZERO);
}
static void
init_dialog_ (void)
{
gint k;
dialog_ = GTK_DIALOG (mixgtk_widget_factory_get_dialog (MIXGTK_WORD_DIALOG));
g_assert (dialog_ != NULL);
for (k = 0; k < SIZE_; ++k)
{
childs_[k] = mixgtk_widget_factory_get_by_name (WGT_NAMES_[k]);
g_assert (childs_[k] != NULL);
}
}
static void
set_word_ (mix_word_t word)
{
enum {SIZE = 50};
static gchar BUFFER[SIZE] = {0};
gint k;
gint val = mix_word_magnitude (word);
gboolean neg = mix_word_is_negative (word);
g_snprintf (BUFFER, SIZE, "%s%d", neg ? "-" : "", val);
g_signal_handlers_block_by_func (childs_[DEC_], on_word_dec_changed, NULL);
g_signal_handlers_block_by_func (childs_[SIGN_], on_word_sign_changed, NULL);
for (k = B1_; k <= B5_; ++k)
g_signal_handlers_block_by_func (childs_[k], on_word_byte_changed, NULL);
gtk_entry_set_text (GTK_ENTRY (childs_[DEC_]), BUFFER);
gtk_entry_set_text (GTK_ENTRY (childs_[SIGN_]), neg ? "-" : "+");
for (k = 1; k < 6; ++k)
{
mix_byte_t b = mix_word_get_byte (word, k);
g_snprintf (BUFFER, SIZE, "%d", (int)b);
gtk_entry_set_text (GTK_ENTRY (childs_[SIGN_ + k]), BUFFER);
}
for (k = B1_; k <= B5_; ++k)
g_signal_handlers_unblock_by_func (childs_[k], on_word_byte_changed, NULL);
g_signal_handlers_unblock_by_func (childs_[DEC_], on_word_dec_changed, NULL);
g_signal_handlers_unblock_by_func (childs_[SIGN_], on_word_sign_changed, NULL);
}
mdk-1.3.1/mixgtk/mixgtk_external.c 0000644 0001750 0001750 00000013047 13743201230 012624 /* -*-c-*- -------------- mixgtk_cmd_dispatcher.c :
* Implementation of the functions declared in mixgtk_external.h
* ------------------------------------------------------------------
* Copyright (C) 2006, 2007, 2008, 2009, 2019, 2020 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*
*/
#include
#include
#include "mixgtk_config.h"
#include "mixgtk_cmd_dispatcher.h"
#include "mixgtk_external.h"
enum {
ext_wdg_ed_chooser,
ext_wdg_ed_entry,
ext_wdg_asm_chooser,
ext_wdg_asm_ls,
ext_wdg_no
};
static GtkWidget *ext_dlg_ = NULL;
static GtkWidget *ext_wdg_[ext_wdg_no] = {NULL, NULL, NULL, NULL};
static const gchar *ext_wdg_names_[] = {
"editor_chooser", "editor_entry", "mixasm_chooser", "mixasm_mls"
};
static const gchar *EDITOR_KEY_ = "Editor";
static const gchar *MIXASM_KEY_ = "Mixasm";
static mix_vm_cmd_dispatcher_t *dispatcher_;
static void init_widgets_ (void);
static void update_dialog_ (void);
static void read_config_ (void);
static void update_config_ (void);
static void update_editor_ (const gchar *cmd);
static void update_asm_ (const gchar *cmd);
void
mixgtk_external_init (mix_vm_cmd_dispatcher_t *dispatcher)
{
g_assert (dispatcher);
dispatcher_ = dispatcher;
init_widgets_ ();
read_config_ ();
}
void
on_external_programs_activate ()
{
if (ext_dlg_)
{
update_dialog_ ();
gtk_widget_show (ext_dlg_);
if (gtk_dialog_run (GTK_DIALOG (ext_dlg_)) == GTK_RESPONSE_OK)
{
update_config_ ();
}
gtk_widget_hide (ext_dlg_);
}
}
void
init_widgets_ (void)
{
gint k;
GtkFileFilter *filter = gtk_file_filter_new ();
g_assert (filter);
ext_dlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_EXTERNPROG_DIALOG);
g_assert (ext_dlg_ != NULL);
for (k = 0; k < ext_wdg_no; ++k)
{
ext_wdg_[k] = mixgtk_widget_factory_get_by_name (ext_wdg_names_[k]);
g_assert (ext_wdg_[k]);
}
gtk_file_filter_add_mime_type (filter, "application/x-executable");
#ifdef EXTRA_EXEC_MIME_TYPE
gtk_file_filter_add_mime_type (filter, "application/octet-stream");
#endif
gtk_file_chooser_set_filter
(GTK_FILE_CHOOSER (ext_wdg_[ext_wdg_asm_chooser]), filter);
gtk_file_chooser_set_filter
(GTK_FILE_CHOOSER (ext_wdg_[ext_wdg_ed_chooser]), filter);
#if GTK_CHECK_VERSION (2,18,0)
gtk_file_chooser_set_create_folders
(GTK_FILE_CHOOSER (ext_wdg_[ext_wdg_asm_chooser]), FALSE);
gtk_file_chooser_set_create_folders
(GTK_FILE_CHOOSER (ext_wdg_[ext_wdg_ed_chooser]), FALSE);
#endif // GTK_CHECK_VERSION
}
void
update_editor_ (const gchar *cmd)
{
mix_vm_cmd_dispatcher_set_editor (dispatcher_, cmd);
mixgtk_config_update (EDITOR_KEY_, cmd);
}
void
update_asm_ (const gchar *cmd)
{
mix_vm_cmd_dispatcher_set_assembler (dispatcher_, cmd);
mixgtk_config_update (MIXASM_KEY_, cmd);
}
void
read_config_ (void)
{
const gchar *editor = mixgtk_config_get (EDITOR_KEY_);
const gchar *assem = mixgtk_config_get (MIXASM_KEY_);
if (!editor)
{
static const gchar *ENV[] = {"MDK_EDITOR", "X_EDITOR", NULL};
gchar *edit = NULL;
int k = 0;
while (!edit && ENV[k]) edit = getenv (ENV[k++]);
if (edit) edit = g_strconcat (edit, " %s", NULL);
else edit = g_strdup (DEFAULT_EDITOR_CMD);
update_editor_ (edit);
g_free (edit);
}
else
{
update_editor_ (editor);
}
update_asm_ (assem? assem : DEFAULT_ASM_CMD);
}
void
update_dialog_ (void)
{
const gchar *editor = mixgtk_config_get (EDITOR_KEY_);
const gchar *assem = mixgtk_config_get (MIXASM_KEY_);
if (editor && assem && ext_dlg_)
{
gchar **parts = g_strsplit_set (editor, " \t", 2);
gboolean is_active;
gtk_file_chooser_select_filename
(GTK_FILE_CHOOSER (ext_wdg_[ext_wdg_ed_chooser]), parts[0]);
gtk_entry_set_text
(GTK_ENTRY (ext_wdg_[ext_wdg_ed_entry]), parts[1]);
g_strfreev (parts);
parts = g_strsplit_set (assem, " \t", 3);
gtk_file_chooser_select_filename
(GTK_FILE_CHOOSER (ext_wdg_[ext_wdg_asm_chooser]), parts[0]);
is_active =
parts[1] && g_ascii_strcasecmp (g_strstrip (parts[1]), "-l") == 0;
gtk_toggle_button_set_active
(GTK_TOGGLE_BUTTON (ext_wdg_[ext_wdg_asm_ls]), is_active);
g_strfreev (parts);
}
}
void
update_config_ (void)
{
gchar *prog = gtk_file_chooser_get_filename
(GTK_FILE_CHOOSER (ext_wdg_[ext_wdg_ed_chooser]));
const gchar *args = gtk_entry_get_text (GTK_ENTRY (ext_wdg_[ext_wdg_ed_entry]));
gchar *cmd = g_strdup_printf ("%s %s", prog, args);
update_editor_ (cmd);
g_free (cmd);
g_free (prog);
prog = gtk_file_chooser_get_filename
(GTK_FILE_CHOOSER (ext_wdg_[ext_wdg_asm_chooser]));
args =
gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ext_wdg_[ext_wdg_asm_ls]))
? " -l "
: " ";
cmd = g_strdup_printf ("%s%s%%s", prog, args);
update_asm_ (cmd);
g_free (cmd);
g_free (prog);
}
mdk-1.3.1/mixgtk/mixgtk_device.c 0000644 0001750 0001750 00000043555 13743201230 012250 /* -*-c-*- ---------------- mixgtk_device.c :
* actual types for mixgtk devices
* ------------------------------------------------------------------
* Copyright (C) 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2019, 2020 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include
#include
#include
#include
#include
#include "mixgtk.h"
#include "mixgtk_gen_handlers.h"
#include "mixgtk_widgets.h"
#include "mixgtk_fontsel.h"
#include "mixgtk_config.h"
#include "mixgtk_cmd_dispatcher.h"
#include "mixgtk_device.h"
#define BIN_DEV_COL_ 5
static const gchar *DEV_FORMAT_KEY_ = "Device.format";
/* device container */
static GtkNotebook *dev_nb_ = NULL;
/* devdir dialog */
static GtkWidget *devdir_dlg_ = NULL;
static GtkEntry *devdir_entry_ = NULL;
/* terminal input dialog */
static GtkWidget *input_dlg_ = NULL;
static GtkEntry *input_dlg_entry_ = NULL;
static GtkListStore *input_list_ = NULL;
/** configuration stuff */
#define LAST_BIN_DEV_ mix_dev_DISK_7
static GtkWidget *devdlg_ = NULL;
static GtkWidget *dtoggle_ = NULL;
static GtkWidget *wtoggle_ = NULL;
static GtkWidget *combo_ = NULL;
/* virtual machine */
static mix_vm_t *vm_ = NULL;
/* dec settings */
static gint32 decs_ = 0;
static gint32 new_decs_ = 0;
/* macros manipulating dec settings */
#define IS_DEC(flags,type) (((flags) >> (type)) & 1)
#define SET_DEC(flags,type) ((flags) |= (1<<(type)))
#define CLEAR_DEC(flags,type) ((flags) &= ~(1<<(type)))
/* a mixgtk device */
struct mixgtk_device_t
{
mix_device_t device;
GtkWidget *widget;
GtkWidget *scroll;
};
struct mixgtk_bin_device_t
{
struct mixgtk_device_t gtk_device;
guint last_insert;
GtkListStore *store;
gboolean dec;
};
/* callbacks for output devices */
static void
write_char_ (struct mixgtk_device_t *dev, const mix_word_t *block)
{
enum {MAX_BLOCK = 24, BUFF_SIZE = MAX_BLOCK * 5 + 2};
static gchar BUFFER[BUFF_SIZE];
guint k, j;
GtkTextIter end;
GtkTextBuffer *buffer;
GtkTextMark *mark;
for (k = 0; k < SIZES_[dev->device.type]; k++)
for (j = 1; j < 6; j++)
{
mix_char_t ch = mix_word_get_byte (block[k], j);
BUFFER[5 * k + j - 1] = mix_char_to_ascii (ch);
}
BUFFER[5 * k] = '\n';
BUFFER[5 * k + 1] = '\0';
buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dev->widget));
gtk_text_buffer_get_end_iter (buffer, &end);
gtk_text_buffer_place_cursor (buffer, &end);
gtk_text_buffer_insert_at_cursor (buffer, BUFFER, -1);
mark = gtk_text_buffer_get_insert (buffer);
gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (dev->widget), mark, 0,
TRUE, 0, 0);
}
static const gchar *
get_word_string_ (mix_word_t w, gboolean dec)
{
enum {BUFF_SIZE = 17};
static gchar BUFFER[BUFF_SIZE] = { 0 };
if (dec)
g_snprintf (BUFFER, BUFF_SIZE, "%s%011ld",
mix_word_is_negative (w)? "-" : "+",
mix_word_magnitude (w));
else
mix_word_print_to_buffer (w, BUFFER);
return BUFFER;
}
static void
write_bin_ (struct mixgtk_bin_device_t *dev, const mix_word_t *block)
{
guint k, col;
gboolean dec = FALSE;
size_t len;
GtkTreeView *view = GTK_TREE_VIEW (dev->gtk_device.widget);
GtkListStore *store = dev->store;
GtkTreeIter iter;
g_assert (view);
g_assert (store);
dec = IS_DEC(decs_, dev->gtk_device.device.type);
for (k = 0, len = SIZES_[dev->gtk_device.device.type];
k < len; k += BIN_DEV_COL_)
{
gtk_list_store_append (store, &iter);
for (col = 0; col < BIN_DEV_COL_; ++col)
gtk_list_store_set (store, &iter,
col, get_word_string_ (block[k + col], dec),
col + BIN_DEV_COL_, (guint)block[k + col],
-1);
dev->last_insert++;
}
}
static gboolean
write_ (mix_device_t *dev, const mix_word_t *block)
{
struct mixgtk_device_t *gtkdev = (struct mixgtk_device_t *) dev;
if (dev->type != mix_dev_CONSOLE && !(DEF_DEV_VTABLE_->write)(dev, block))
return FALSE;
if (MODES_[dev->type] == mix_dev_CHAR) write_char_ (gtkdev, block);
else write_bin_ ((struct mixgtk_bin_device_t *)gtkdev, block);
gtk_notebook_set_current_page (dev_nb_,
gtk_notebook_page_num (dev_nb_,
gtkdev->scroll));
return TRUE;
}
static void
init_input_widgets_ (void)
{
input_dlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_INPUT_DIALOG);
g_assert (input_dlg_);
input_dlg_entry_ =
GTK_ENTRY (mixgtk_widget_factory_get_by_name ("input_entry"));
g_assert (input_dlg_entry_);
GtkEntryCompletion *completion = gtk_entry_completion_new ();
input_list_ = gtk_list_store_new (1, G_TYPE_STRING);
gtk_entry_completion_set_model (completion, GTK_TREE_MODEL (input_list_));
gtk_entry_completion_set_popup_completion (completion, TRUE);
#if GTK_CHECK_VERSION(2,8,0)
gtk_entry_completion_set_popup_single_match (completion, TRUE);
#endif
gtk_entry_completion_set_inline_completion (completion, FALSE);
gtk_entry_completion_set_minimum_key_length (completion, 1);
gtk_entry_completion_set_text_column (completion, 0);
gtk_entry_set_completion (input_dlg_entry_, completion);
gtk_widget_hide (input_dlg_);
}
static gboolean
find_input_ (const gchar *text)
{
GtkTreeModel *list_store = GTK_TREE_MODEL (input_list_);
GtkTreeIter iter;
gboolean valid = gtk_tree_model_get_iter_first (list_store, &iter);
gboolean found = FALSE;
while (valid && !found)
{
gchar *str_data;
gtk_tree_model_get (list_store, &iter, 0, &str_data, -1);
found = (g_ascii_strcasecmp (str_data, text) == 0);
valid = gtk_tree_model_iter_next (list_store, &iter);
g_free (str_data);
}
return found;
}
static gboolean
read_cons_ (mix_word_t *block)
{
gchar *text;
size_t i, j;
if (input_dlg_ == NULL)
{
init_input_widgets_ ();
}
gtk_entry_set_text (input_dlg_entry_, "");
gint result = gtk_dialog_run (GTK_DIALOG (input_dlg_));
gtk_widget_hide (input_dlg_);
if (result == GTK_RESPONSE_OK)
{
text = g_strdup_printf ("%-70s", gtk_entry_get_text (input_dlg_entry_));
for (i = 0; i < SIZES_[mix_dev_CONSOLE]; ++i)
for (j = 0; j < 5; ++j)
mix_word_set_byte (block + i, j + 1,
mix_char_to_byte
(mix_ascii_to_char (text[5 * i + j])));
if (!find_input_ (g_strchomp (text)))
{
GtkTreeIter iter;
gtk_list_store_append (input_list_, &iter);
gtk_list_store_set (input_list_, &iter, 0, text, -1);
}
g_free (text);
}
return TRUE;
}
static gboolean
read_ (mix_device_t *dev, mix_word_t *block)
{
struct mixgtk_device_t *gtkdev = (struct mixgtk_device_t *) dev;
if (dev->type == mix_dev_CONSOLE && !read_cons_ (block)) return FALSE;
if (dev->type != mix_dev_CONSOLE && !(DEF_DEV_VTABLE_->read)(dev, block))
return FALSE;
if (MODES_[dev->type] == mix_dev_CHAR) write_char_ (gtkdev, block);
else write_bin_ ((struct mixgtk_bin_device_t *)gtkdev, block);
gtk_notebook_set_current_page (dev_nb_,
gtk_notebook_page_num (dev_nb_,
gtkdev->scroll));
return TRUE;
}
static gboolean
ioc_ (mix_device_t *dev, mix_short_t cmd, mix_word_t val)
{
return (DEF_DEV_VTABLE_->ioc)(dev, cmd, val);
}
static gboolean
busy_ (const mix_device_t *dev)
{
return (DEF_DEV_VTABLE_->busy)(dev);
}
static void
destroy_ (mix_device_t *dev)
{
struct mixgtk_device_t *gtkdev = (struct mixgtk_device_t *)dev;
if (MODES_[dev->type] == mix_dev_BIN) {
struct mixgtk_bin_device_t * bdev = (struct mixgtk_bin_device_t *)dev;
gtk_list_store_clear (bdev->store);
g_object_unref ((gpointer)bdev->store);
}
(DEF_DEV_VTABLE_->destroy) (dev);
gtk_notebook_remove_page (dev_nb_,
gtk_notebook_page_num (dev_nb_,
gtkdev->scroll));
}
static mix_device_vtable_t MIXGTK_VTABLE_ = {
write_, read_, ioc_, busy_, destroy_
};
/* create the gui part of the device */
static void
mixgtk_device_construct_gui_ (struct mixgtk_device_t *dev)
{
GtkWidget *label = gtk_label_new (DEF_NAMES_[dev->device.type]);
g_assert (label);
dev->scroll = gtk_scrolled_window_new (NULL, NULL);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (dev->scroll),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
if (MODES_[dev->device.type] == mix_dev_CHAR)
{
dev->widget = gtk_text_view_new ();
gtk_text_view_set_editable (GTK_TEXT_VIEW (dev->widget), FALSE);
}
else
{
gint k;
struct mixgtk_bin_device_t *bindev = (struct mixgtk_bin_device_t *)dev;
GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
GType *types = g_new (GType, BIN_DEV_COL_ * 2);
for (k = 0; k < BIN_DEV_COL_; ++k)
{
types[k] = G_TYPE_STRING;
types[k + BIN_DEV_COL_] = G_TYPE_UINT;
}
bindev->store = gtk_list_store_newv (BIN_DEV_COL_ * 2, types);
dev->widget =
gtk_tree_view_new_with_model (GTK_TREE_MODEL (bindev->store));
gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (dev->widget), FALSE);
// gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (dev->widget), TRUE);
for (k = 0; k < BIN_DEV_COL_; ++k)
{
gtk_tree_view_append_column
(GTK_TREE_VIEW (dev->widget),
gtk_tree_view_column_new_with_attributes ("", renderer,
"text", k, NULL));
}
g_free (types);
}
g_assert (dev->widget);
gtk_container_add (GTK_CONTAINER (dev->scroll), dev->widget);
mixgtk_fontsel_set_font (MIX_FONT_DEVICES, dev->widget);
gtk_notebook_append_page (dev_nb_, dev->scroll, label);
gtk_widget_show (label);
gtk_widget_show (dev->scroll);
gtk_widget_show (dev->widget);
}
static void
redraw_bin_device_ (struct mixgtk_bin_device_t *dev)
{
if (dev != NULL)
{
GtkTreeModel *store = GTK_TREE_MODEL (dev->store);
GtkTreeIter iter;
gboolean valid;
g_assert (store);
valid =
gtk_tree_model_get_iter_first (store, &iter);
while (valid)
{
gint k;
guint word;
for (k = 0; k < BIN_DEV_COL_; ++k)
{
gtk_tree_model_get (store, &iter, k + BIN_DEV_COL_, &word, -1);
gtk_list_store_set (GTK_LIST_STORE (store), &iter,
k, get_word_string_ ((mix_word_t)word,
dev->dec),
-1);
}
valid = gtk_tree_model_iter_next (store, &iter);
}
gtk_widget_queue_draw (((struct mixgtk_device_t *)dev)->widget);
}
}
/* create a new mixgtk device */
static mix_device_t *
mixgtk_device_new_ (mix_device_type_t type)
{
struct mixgtk_device_t *dev = NULL;
g_return_val_if_fail (type < mix_dev_INVALID, NULL);
if (MODES_[type] == mix_dev_CHAR)
{
dev = g_new (struct mixgtk_device_t, 1);
}
else
{
dev = (struct mixgtk_device_t *) g_new (struct mixgtk_bin_device_t, 1);
((struct mixgtk_bin_device_t *)dev)->last_insert = 0;
}
construct_device_ (&dev->device, type);
dev->device.vtable = &MIXGTK_VTABLE_;
mixgtk_device_construct_gui_ (dev);
return (mix_device_t *)dev;
}
/* init default devices */
GtkWidget *
mixgtk_device_init (mix_vm_t *vm)
{
g_assert (vm != NULL);
vm_ = vm;
devdlg_ = NULL;
devdir_dlg_ = NULL;
devdir_entry_ = NULL;
input_dlg_ = NULL;
dtoggle_ = NULL;
wtoggle_ = NULL;
combo_ = NULL;
if (dev_nb_ == NULL)
{
mix_vm_set_device_factory (vm, mixgtk_device_new_);
/* read format configuration */
if (mixgtk_config_get (DEV_FORMAT_KEY_))
decs_ = atoi (mixgtk_config_get (DEV_FORMAT_KEY_));
dev_nb_ = GTK_NOTEBOOK (gtk_notebook_new ());
gtk_notebook_set_tab_pos (dev_nb_, GTK_POS_RIGHT);
gtk_notebook_set_scrollable (dev_nb_, FALSE);
}
mixgtk_fontsel_set_font (MIX_FONT_DEVICES, GTK_WIDGET (dev_nb_));
return GTK_WIDGET (dev_nb_);
}
void
mixgtk_device_set_format (mix_device_type_t dev, gboolean dec)
{
gboolean changed;
g_return_if_fail (dev < mix_dev_INVALID);
changed = (dec && !IS_DEC (decs_, dev)) || (!dec && IS_DEC (decs_, dev));
if (changed && (MODES_[dev] == mix_dev_BIN))
{
struct mixgtk_bin_device_t *gdev =
(struct mixgtk_bin_device_t *) mix_vm_get_device (vm_, dev);
if (gdev != NULL)
{
if (dec) SET_DEC (decs_, dev); else CLEAR_DEC (decs_, dev);
gdev->dec = !(gdev->dec);
redraw_bin_device_ (gdev);
}
}
}
static gpointer
combo_child_ ()
{
return gtk_bin_get_child (GTK_BIN (combo_));
}
static mix_device_type_t
get_device_idx_ (void)
{
int k;
const gchar *name = gtk_entry_get_text (GTK_ENTRY (combo_child_ ()));
for (k = 0; k <= LAST_BIN_DEV_; ++k)
if (!strcmp (name, DEF_NAMES_[k])) break;
return k;
}
static void
init_devform_ (void)
{
devdlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_DEVFORM_DIALOG);
g_assert (devdlg_);
dtoggle_ = mixgtk_widget_factory_get_by_name ("decradio");
g_assert (dtoggle_);
wtoggle_ = mixgtk_widget_factory_get_by_name ("wordradio");
g_assert (wtoggle_);
combo_ = mixgtk_widget_factory_get_by_name ("dev_combo");
g_assert (combo_);
gtk_editable_set_editable (GTK_EDITABLE (combo_child_ ()), FALSE);
}
void
on_dev_combo_changed ()
{
mix_device_type_t dev = get_device_idx_ ();
if (dev <= LAST_BIN_DEV_)
{
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dtoggle_),
IS_DEC (new_decs_, dev));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (wtoggle_),
!IS_DEC (new_decs_, dev));
}
}
void
on_devform_activate ()
{
gint result = GTK_RESPONSE_APPLY;
if (!devdlg_) init_devform_ ();
new_decs_ = decs_;
while (result == GTK_RESPONSE_APPLY)
{
//on_dev_combo_changed ();
result = gtk_dialog_run (GTK_DIALOG (devdlg_));
if (result != GTK_RESPONSE_CANCEL)
{
int k;
gchar value[20];
for (k = 0; k <= LAST_BIN_DEV_; ++k)
mixgtk_device_set_format (k, IS_DEC (new_decs_, k));
decs_ = new_decs_;
g_snprintf (value, 20, "%d", decs_);
mixgtk_config_update (DEV_FORMAT_KEY_, value);
}
}
gtk_widget_hide (devdlg_);
}
void
on_decradio_toggled (GtkToggleButton *button)
{
if (gtk_toggle_button_get_active (button))
SET_DEC (new_decs_, get_device_idx_ ());
else
CLEAR_DEC (new_decs_, get_device_idx_ ());
}
void
on_devset_button_clicked ()
{
static gint32 ON = 0xffff, OFF = 0;
new_decs_ = (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dtoggle_)))?
ON : OFF;
}
void
on_devdir_activate ()
{
static const gchar *DEVDIR_ENTRY_NAME = "devdir_entry";
if (devdir_dlg_ == NULL)
{
devdir_dlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_DEVDIR_DIALOG);
g_assert (devdir_dlg_);
devdir_entry_ =
GTK_ENTRY (mixgtk_widget_factory_get_by_name (DEVDIR_ENTRY_NAME));
g_assert (devdir_entry_);
}
gtk_entry_set_text (devdir_entry_, mix_device_get_dir ());
gtk_widget_show (devdir_dlg_);
}
void
on_devdir_browse_clicked ()
{
GtkWidget *dialog;
const gchar *current = gtk_entry_get_text (devdir_entry_);
dialog =
gtk_file_chooser_dialog_new (_("Devices folder"),
GTK_WINDOW (devdir_dlg_),
GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Open", GTK_RESPONSE_ACCEPT,
NULL);
if (current != NULL)
gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), current);
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
{
char *filename
= gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
gtk_entry_set_text (devdir_entry_, filename);
g_free (filename);
}
gtk_widget_destroy (dialog);
}
void
on_devdir_cancel_clicked ()
{
gtk_widget_hide (devdir_dlg_);
}
void
on_devdir_ok_clicked ()
{
const gchar *dirname = gtk_entry_get_text (devdir_entry_);
gchar *cmd = g_strconcat (mix_vm_command_to_string (MIX_CMD_SDDIR),
" ", dirname, NULL);
gtk_widget_hide (devdir_dlg_);
mixgtk_cmd_dispatcher_dispatch (cmd);
g_free (cmd);
}
/* fonts */
static GtkWidget **
font_widgets_ (gint * n)
{
gint no = gtk_notebook_get_n_pages (dev_nb_);
GtkWidget **w = g_new (GtkWidget *, no + 1);
gint k, j;
for (k = 0, j = 0; k < no && j < mix_dev_INVALID; ++j)
{
struct mixgtk_device_t * dev =
(struct mixgtk_device_t *) mix_vm_get_device (vm_, j);
if (dev != NULL) w[k++] = dev->widget;
}
g_assert (k == no);
w[k] = GTK_WIDGET (dev_nb_);
if (n) *n = no;
return w;
}
void
on_devices_font_activate ()
{
gint no = 0;
GtkWidget **w = font_widgets_ (&no);
mixgtk_fontsel_query_font (MIX_FONT_DEVICES, w, no + 1);
g_free (w);
}
void
mixgtk_device_update_fonts (void)
{
gint k, n = 0;
GtkWidget **w = font_widgets_ (&n);
g_assert (n >= 0);
for (k = 0; k < n; ++k)
mixgtk_fontsel_set_font (MIX_FONT_DEVICES, w[k]);
}
mdk-1.3.1/mixgtk/mixgtk_mixal.c 0000644 0001750 0001750 00000037156 13743201230 012123 /* -*-c-*- -------------- mixgtk_mixal.c :
* Implementation of the functions declared in mixgtk_mixal.h
* ------------------------------------------------------------------
* Copyright (C) 2001, 2002, 2004, 2006, 2007, 2019, 2020 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include
#include
#include "mixgtk_widgets.h"
#include "mixgtk_config.h"
#include "mixgtk_fontsel.h"
#include "mixgtk_mixal.h"
static mix_vm_t *vm_ = NULL;
static GtkTreeView *clist_ = NULL;
static GtkListStore *clist_store_ = NULL;
static gulong lineno_;
static GtkStatusbar *status_ = NULL;
static gint status_context_ = 0;
static GPtrArray *tips_text_ = NULL;
static GtkWidget *symbols_dlg_ = NULL;
static GtkTreeView *symbols_view_ = NULL;
static GtkListStore *symbols_store_ = NULL;
static const gchar *SYMBOLS_VIEW_NAME_ = "symbols_view";
static const gchar *bp_stock_id_ = "gtk-stop";
static const gchar *pc_stock_id_ = "gtk-go-forward";
static const guint bp_stock_size_ = GTK_ICON_SIZE_MENU;
enum {
CLIST_BP_ID_COL,
CLIST_BP_SIZE_COL,
CLIST_ADDRESS_COL,
CLIST_BYTECODE_COL,
CLIST_CODE_COL,
CLIST_ADDRESS_NO_COL,
CLIST_LINE_NO_COL,
CLIST_COL_NO
};
enum {
SYMBOLS_NAME_COL,
SYMBOLS_VALUE_COL,
SYMBOLS_WORD_COL,
SYMBOLS_COL_NO
};
static gboolean
mixal_event_ (GtkWidget *w, GdkEvent *event, gpointer data);
static void
init_symbols_ (void)
{
GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
symbols_dlg_ = mixgtk_widget_factory_get_dialog (MIXGTK_SYMBOLS_DIALOG);
g_assert (symbols_dlg_);
symbols_view_ = GTK_TREE_VIEW
(mixgtk_widget_factory_get_by_name (SYMBOLS_VIEW_NAME_));
g_assert (symbols_view_);
mixgtk_fontsel_set_font (MIX_FONT_SYMBOLS, GTK_WIDGET (symbols_view_));
symbols_store_ = gtk_list_store_new (SYMBOLS_COL_NO,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING);
gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (symbols_store_),
SYMBOLS_NAME_COL,
GTK_SORT_ASCENDING);
gtk_tree_view_set_model (symbols_view_, GTK_TREE_MODEL (symbols_store_));
g_object_unref (G_OBJECT (symbols_store_));
gtk_tree_view_append_column
(symbols_view_,
gtk_tree_view_column_new_with_attributes ("Name", renderer,
"text", SYMBOLS_NAME_COL,
NULL));
gtk_tree_view_append_column
(symbols_view_,
gtk_tree_view_column_new_with_attributes ("Value", renderer,
"text", SYMBOLS_VALUE_COL,
NULL));
gtk_tree_view_append_column
(symbols_view_,
gtk_tree_view_column_new_with_attributes ("", renderer,
"text", SYMBOLS_WORD_COL,
NULL));
}
static void
insert_symbol_ (gpointer symbol, gpointer value, gpointer data)
{
enum {DEC_SIZE = 25, WORD_SIZE = 20};
static gchar DEC[DEC_SIZE], WORD[WORD_SIZE];
GtkTreeIter iter;
mix_word_t w = (mix_word_t)GPOINTER_TO_INT (value);
g_snprintf (DEC, DEC_SIZE, "%s%ld",
mix_word_is_negative (w)? "-" : "+",
mix_word_magnitude (w));
mix_word_print_to_buffer (w, WORD);
gtk_list_store_append (symbols_store_, &iter);
gtk_list_store_set (symbols_store_, &iter,
SYMBOLS_NAME_COL, (const gchar*)symbol,
SYMBOLS_VALUE_COL, DEC,
SYMBOLS_WORD_COL, WORD,
-1);
}
static void
fill_symbols_ (const mix_symbol_table_t *table)
{
if (symbols_view_)
gtk_list_store_clear (symbols_store_);
else
init_symbols_ ();
mix_symbol_table_foreach (((mix_symbol_table_t *)table),
insert_symbol_, NULL);
}
static void
init_clist_ (void)
{
GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
GtkCellRenderer *bprenderer = gtk_cell_renderer_pixbuf_new ();
clist_ = GTK_TREE_VIEW (gtk_tree_view_new ());
clist_store_ = gtk_list_store_new (CLIST_COL_NO,
G_TYPE_STRING,
G_TYPE_INT,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_STRING,
G_TYPE_INT,
G_TYPE_INT);
gtk_tree_view_set_model (clist_, GTK_TREE_MODEL (clist_store_));
g_object_unref (G_OBJECT (clist_store_));
// gtk_tree_view_set_rules_hint (clist_, TRUE);
gtk_tree_view_append_column
(clist_,
gtk_tree_view_column_new_with_attributes ("", bprenderer,
"stock-id", CLIST_BP_ID_COL,
"stock-size", CLIST_BP_SIZE_COL,
NULL));
gtk_tree_view_append_column
(clist_,
gtk_tree_view_column_new_with_attributes ("Address", renderer,
"text", CLIST_ADDRESS_COL,
NULL));
gtk_tree_view_append_column
(clist_,
gtk_tree_view_column_new_with_attributes ("Bytecode", renderer,
"text", CLIST_BYTECODE_COL,
NULL));
gtk_tree_view_append_column
(clist_,
gtk_tree_view_column_new_with_attributes ("Source", renderer,
"text", CLIST_CODE_COL,
NULL));
symbols_dlg_ = NULL;
symbols_view_ = NULL;
g_signal_connect (G_OBJECT (clist_), "event",
G_CALLBACK (mixal_event_), NULL);
mixgtk_fontsel_set_font (MIX_FONT_MIXAL, GTK_WIDGET (clist_));
gtk_widget_show (GTK_WIDGET (clist_));
}
/* initialise the mixal widgets */
GtkWidget *
mixgtk_mixal_init (mix_vm_t *vm)
{
if (vm != NULL) vm_ = vm;
if (vm_ == NULL) return FALSE;
if (clist_ == NULL) init_clist_ ();
status_ = NULL;
return GTK_WIDGET (clist_);
}
void
mixgtk_mixal_reparent (GtkStatusbar *status)
{
g_assert (status != NULL);
mixgtk_mixal_pop_status ();
status_ = status;
status_context_ = gtk_statusbar_get_context_id (status_, "MIXAL status");
}
void
mixgtk_mixal_update_fonts (void)
{
mixgtk_fontsel_set_font (MIX_FONT_MIXAL, GTK_WIDGET (clist_));
mixgtk_fontsel_set_font (MIX_FONT_SYMBOLS, GTK_WIDGET (symbols_view_));
}
void
mixgtk_mixal_pop_status (void)
{
if (status_ != NULL)
gtk_statusbar_pop (status_, status_context_);
}
/* load the corresponding mixal file */
static void
update_tips_ (const mix_symbol_table_t *table,
const gchar *line)
{
enum {SIZE = 256};
static gchar BUFFER[256];
static const gchar *DELIMITERS = " /+*=-()\t,:\n";
if (line)
{
guint k = 0;
gchar *tip = g_strdup ("");
gchar *new_tip;
gchar **tokens;
gchar *text = g_strdup (line);
text = g_strdelimit (text, DELIMITERS, ' ');
tokens = g_strsplit (g_strstrip (text), " ", -1);
while (tokens[k])
{
if (mix_symbol_table_is_defined (table, tokens[k]))
{
mix_word_t val = mix_symbol_table_value (table, tokens[k]);
g_snprintf (BUFFER, SIZE, "[ %s = %s%ld ]", tokens[k],
mix_word_is_negative (val)? "-" : "+",
mix_word_magnitude (val));
new_tip = g_strconcat (tip, " ", BUFFER, NULL);
g_free (tip);
tip = new_tip;
}
++k;
}
g_ptr_array_add (tips_text_, (gpointer)tip);
g_strfreev (tokens);
g_free (text);
}
}
void
mixgtk_mixal_load_file (void)
{
enum {ADDR_SIZE = 20, CONT_SIZE = 200, WORD_SIZE = 20};
static gchar ADDR[ADDR_SIZE], CONT[CONT_SIZE], WORD[WORD_SIZE];
const mix_src_file_t *file;
GtkTreeIter iter;
g_assert (vm_);
g_assert (clist_);
gtk_list_store_clear (clist_store_);
if (tips_text_)
{
g_ptr_array_free (tips_text_, TRUE);
tips_text_ = NULL;
}
file = mix_vm_get_src_file (vm_);
if (file != NULL)
{
gint k;
mix_address_t addr;
const mix_symbol_table_t *table = mix_vm_get_symbol_table (vm_);
if (table) tips_text_ = g_ptr_array_new ();
lineno_ = mix_src_file_get_line_no (file);
for (k = 0; k < lineno_; ++k)
{
gchar *line =
g_strchomp ((gchar *)mix_src_file_get_line (file, k + 1));
g_snprintf (CONT, CONT_SIZE, " %03d: %s", k + 1, line);
addr = mix_vm_get_lineno_address (vm_, k + 1);
if (addr != MIX_VM_CELL_NO)
{
g_snprintf (ADDR, ADDR_SIZE, "%04d", mix_short_magnitude (addr));
mix_word_print_to_buffer (mix_vm_get_addr_contents (vm_, addr),
WORD);
}
else
{
g_snprintf (ADDR, ADDR_SIZE, _("N/A"));
g_snprintf (WORD, WORD_SIZE, _("N/A"));
}
gtk_list_store_append (clist_store_, &iter);
gtk_list_store_set (clist_store_, &iter,
CLIST_ADDRESS_NO_COL, mix_short_magnitude (addr),
CLIST_LINE_NO_COL, k + 1,
CLIST_ADDRESS_COL, ADDR,
CLIST_CODE_COL, CONT,
CLIST_BYTECODE_COL, WORD,
CLIST_BP_SIZE_COL, bp_stock_size_,
-1);
if (table) update_tips_ (table, line);
}
if (table) fill_symbols_ (table);
}
else
{
lineno_ = 0;
gtk_list_store_append (clist_store_, &iter);
gtk_list_store_set (clist_store_, &iter,
CLIST_ADDRESS_NO_COL, MIX_VM_CELL_NO,
CLIST_LINE_NO_COL, 0,
CLIST_ADDRESS_COL, "",
CLIST_CODE_COL, _("Source not available"),
CLIST_BYTECODE_COL, "",
-1);
}
}
/* update the widgets */
static gint
find_address_ (gint address)
{
GtkTreeIter iter;
gint addr;
gint row = 0;
gboolean valid =
gtk_tree_model_get_iter_first (GTK_TREE_MODEL (clist_store_), &iter);
while (valid)
{
++row;
gtk_tree_model_get (GTK_TREE_MODEL (clist_store_), &iter,
CLIST_ADDRESS_NO_COL, &addr, -1);
if (addr == address) return row;
valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (clist_store_), &iter);
}
return 0;
}
static void
update_bp_ (gint row)
{
if (row > 0)
{
GtkTreePath *path = gtk_tree_path_new_from_indices (row - 1, -1);
GtkTreeIter iter;
if (gtk_tree_model_get_iter (GTK_TREE_MODEL (clist_store_), &iter, path))
{
gint address;
const gchar *id = NULL;
gtk_tree_model_get (GTK_TREE_MODEL (clist_store_), &iter,
CLIST_ADDRESS_NO_COL, &address, -1);
if (mix_vm_has_breakpoint_at_address (vm_, address))
id = bp_stock_id_;
else if (address ==
(gint) mix_short_magnitude (mix_vm_get_prog_count (vm_)))
id = pc_stock_id_;
gtk_list_store_set (clist_store_, &iter, CLIST_BP_ID_COL, id, -1);
}
gtk_tree_path_free (path);
}
}
static void
select_row_ (gint row)
{
static gint previous = 0;
if (row > 0 && previous != row)
{
GtkTreePath *path = gtk_tree_path_new_from_indices (row - 1, -1);
GtkTreeIter iter;
if (gtk_tree_model_get_iter (GTK_TREE_MODEL (clist_store_), &iter, path))
{
gtk_list_store_set (clist_store_, &iter,
CLIST_BP_ID_COL, pc_stock_id_,
-1);
update_bp_ (previous);
previous = row;
gtk_tree_view_scroll_to_cell (clist_, path, NULL, FALSE, 0.3, 0);
}
gtk_tree_path_free (path);
}
}
void
mixgtk_mixal_update (void)
{
gint addr = 0;
g_assert (vm_);
addr = (gint) mix_short_magnitude (mix_vm_get_prog_count (vm_));
select_row_ (find_address_ (addr));
}
/* breakpoints */
void
mixgtk_mixal_update_bp_at_address (guint addr)
{
update_bp_ (find_address_ ((gint)addr));
}
void
mixgtk_mixal_update_bp_at_line (guint line)
{
update_bp_ ((gint)line);
}
void
mixgtk_mixal_update_bp_all (void)
{
gint k;
for (k = 1; k <= lineno_; ++k) update_bp_ (k);
mixgtk_mixal_update ();
}
/* callbacks */
static void
mixal_row_clicked_ (GtkTreeIter *iter)
{
gint addr = MIX_VM_CELL_NO;
gtk_tree_model_get (GTK_TREE_MODEL (clist_store_),
iter, CLIST_ADDRESS_NO_COL, &addr, -1);
if (addr < MIX_VM_CELL_NO)
{
gboolean isset = mix_vm_has_breakpoint_at_address (vm_, addr);
if (isset)
mix_vm_clear_breakpoint_address (vm_, addr);
else
mix_vm_set_breakpoint_address (vm_, addr);
update_bp_ (find_address_ (addr));
}
}
static void
mixal_motion_ (GtkTreeIter *iter)
{
static gint last_row = 0;
static guint last_message = 0;
gint row = last_row;
gtk_tree_model_get (GTK_TREE_MODEL (clist_store_), iter,
CLIST_LINE_NO_COL, &row, -1);
if (row > 0 && row != last_row && tips_text_)
{
const gchar *msg = NULL;
last_row = row;
if (last_message)
gtk_statusbar_remove (status_, status_context_, last_message);
msg = (const gchar *)g_ptr_array_index (tips_text_, row - 1);
if (msg)
last_message = gtk_statusbar_push (status_, status_context_, msg);
else
last_message = 0;
}
}
static gboolean
mixal_event_ (GtkWidget *w, GdkEvent *event, gpointer data)
{
GdkEventType type = event->type;
if ((type == GDK_BUTTON_PRESS || type == GDK_MOTION_NOTIFY)
&& (gtk_tree_view_get_bin_window (clist_) == event->any.window))
{
gdouble x = (type == GDK_BUTTON_PRESS)? event->button.x : event->motion.x;
gdouble y = (type == GDK_BUTTON_PRESS)? event->button.y : event->motion.y;
GtkTreeIter iter;
GtkTreePath *path = NULL;
GtkTreeViewColumn *col = NULL;
if (gtk_tree_view_get_path_at_pos (clist_, x, y, &path, &col, NULL, NULL)
&& gtk_tree_model_get_iter (GTK_TREE_MODEL (clist_store_),
&iter, path))
{
if (type == GDK_BUTTON_PRESS) mixal_row_clicked_ (&iter);
else mixal_motion_ (&iter);
}
if (path) gtk_tree_path_free (path);
return TRUE;
}
return FALSE;
}
void
on_symbol_ok_clicked ()
{
gtk_widget_hide (symbols_dlg_);
}
void
on_symbols_activate ()
{
if (!symbols_dlg_) init_symbols_ ();
gtk_widget_show (symbols_dlg_);
}
void
on_mixal_leave_notify_event ()
{
if (status_ != NULL) gtk_statusbar_pop (status_, status_context_);
}
void
on_mixal_font_activate ()
{
GtkWidget *w[] = { GTK_WIDGET (clist_) };
mixgtk_fontsel_query_font (MIX_FONT_MIXAL, w, 1);
}
void
on_symbols_font_activate ()
{
if (symbols_view_ != NULL)
{
GtkWidget *w[] = { GTK_WIDGET (symbols_view_) };
mixgtk_fontsel_query_font (MIX_FONT_SYMBOLS, w, 1);
}
else
mixgtk_fontsel_query_font (MIX_FONT_SYMBOLS, NULL, 0);
}
mdk-1.3.1/mixgtk/mixgtk_fontsel.c 0000644 0001750 0001750 00000007661 13743201230 012461 /* -*-c-*- -------------- mixgtk_fontsel.c :
* Implementation of the functions declared in mixgtk_fontsel.h
* ------------------------------------------------------------------
* Copyright (C) 2001, 2004, 2006, 2007, 2008, 2019, 2020 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include
#include "mixgtk_widgets.h"
#include "mixgtk_config.h"
#include "mixgtk_mixvm.h"
#include "mixgtk_mixal.h"
#include "mixgtk_cmd_dispatcher.h"
#include "mixgtk_device.h"
#include "mixgtk_fontsel.h"
static GtkFontChooserDialog *fontsel_dialog_ = NULL;
#define FONTSEL_ GTK_FONT_CHOOSER (fontsel_dialog_)
static const gchar *keys_[MIX_FONT_NO] = {
"MIX.font", "Prompt.font", "Log.font", "MIXAL.font", "Devices.font",
"Symbols.font", "Default.font"
};
static const gchar *default_font_ = "Monospace 10";
/* initialise the font selection dialog */
static void
init_fontsel_ (void)
{
fontsel_dialog_ =
GTK_FONT_CHOOSER_DIALOG
(mixgtk_widget_factory_get_dialog (MIXGTK_FONTSEL_DIALOG));
g_assert (fontsel_dialog_ != NULL);
}
void
mixgtk_fontsel_set_font (mixgtk_font_t f, GtkWidget *w)
{
const gchar *font;
PangoFontDescription *font_desc;
if (f >= MIX_FONT_NO || w == NULL) return;
font = mixgtk_config_get (keys_[f]);
if (!font)
{
mixgtk_config_update (keys_[f], default_font_);
font = mixgtk_config_get (keys_[f]);
g_assert (font);
}
font_desc = pango_font_description_from_string (font);
if (font_desc)
{
gtk_widget_override_font (w, font_desc);
pango_font_description_free (font_desc);
}
else
mixgtk_config_remove (keys_[f]);
}
gboolean
mixgtk_fontsel_query_font (mixgtk_font_t f, GtkWidget **w, size_t no)
{
gint result = GTK_RESPONSE_APPLY;
const gchar *current;
gboolean ret = FALSE;
if (f >= MIX_FONT_NO) return FALSE;
if (!fontsel_dialog_) init_fontsel_ ();
current = mixgtk_config_get (keys_[f]);
gtk_font_chooser_set_font (FONTSEL_, current? current : default_font_);
while (result == GTK_RESPONSE_APPLY)
{
result = gtk_dialog_run (GTK_DIALOG (fontsel_dialog_));
if (result != GTK_RESPONSE_CANCEL)
{
gint k;
mixgtk_config_update
(keys_[f],
gtk_font_chooser_get_font (FONTSEL_));
for (k = 0; k < no; ++k)
mixgtk_fontsel_set_font (f, w[k]);
ret = TRUE;
}
}
gtk_widget_hide (GTK_WIDGET (fontsel_dialog_));
return ret;
}
void
on_all_fonts_activate (void)
{
gint result = GTK_RESPONSE_APPLY;
const gchar *current;
if (!fontsel_dialog_) init_fontsel_ ();
current = mixgtk_config_get (keys_[MIX_FONT_DEFAULT]);
gtk_font_chooser_set_font (FONTSEL_, current? current : default_font_);
while (result == GTK_RESPONSE_APPLY)
{
result = gtk_dialog_run (GTK_DIALOG (fontsel_dialog_));
if (result != GTK_RESPONSE_CANCEL)
{
gint k;
current = gtk_font_chooser_get_font (FONTSEL_);
for (k = 0; k < MIX_FONT_NO; ++k)
mixgtk_config_update (keys_[k], current);
mixgtk_mixal_update_fonts ();
mixgtk_mixvm_update_fonts ();
mixgtk_device_update_fonts ();
mixgtk_cmd_dispatcher_update_fonts ();
}
}
gtk_widget_hide (GTK_WIDGET (fontsel_dialog_));
}
mdk-1.3.1/mixgtk/mixgtk.h 0000644 0001750 0001750 00000002446 12112755472 010743 /* -*-c-*- ---------------- mixgtk.h :
* Gmixvm initialisation and cleanup functions
* ------------------------------------------------------------------
* Copyright (C) 2001, 2004, 2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef MIXGTK_H
#define MIXGTK_H
#include
#include
/* the app files directory */
#define MIXGTK_FILES_DIR ".mdk"
/* initialise the app */
extern gboolean
mixgtk_init (int argc, char *argv[]);
/* enter the main mixgtk loop */
extern void
mixgtk_main (void);
/* clean up */
extern void
mixgtk_release (void);
#endif /* MIXGTK_H */
mdk-1.3.1/mixgtk/mixgtk_gen_handlers.c 0000644 0001750 0001750 00000012405 13743201230 013430 /* -*-c-*- -------------- mixgtk_gen_handlers.c :
* Implementation of the functions declared in mixgtk_gen_handlers.h
* ------------------------------------------------------------------
* Copyright (C) 2001, 2002, 2004, 2006, 2007, 2019 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include
#include "mixgtk_gen_handlers.h"
#include "mixgtk_cmd_dispatcher.h"
#include "mixgtk_config.h"
/* grab a file with an externally provided callback */
typedef void (*file_callback_t)(const gchar *file);
static GtkFileChooser *
get_chooser_ (const gchar *title, gboolean src)
{
static GtkFileChooser *dialog = NULL;
static GtkFileFilter *src_filter = NULL;
static GtkFileFilter *code_filter = NULL;
if (dialog == NULL)
{
dialog = GTK_FILE_CHOOSER
(gtk_file_chooser_dialog_new ("gmixvm",
NULL,
GTK_FILE_CHOOSER_ACTION_OPEN,
"_Cancel", GTK_RESPONSE_CANCEL,
"_Open", GTK_RESPONSE_ACCEPT,
NULL));
src_filter = gtk_file_filter_new ();
gtk_file_filter_add_pattern (src_filter, "*.mixal");
gtk_file_filter_set_name (src_filter, "MIXAL files");
code_filter = gtk_file_filter_new ();
gtk_file_filter_add_pattern (code_filter, "*.mix");
gtk_file_filter_set_name (code_filter, "MIX files");
gtk_file_chooser_add_filter (dialog, src_filter);
gtk_file_chooser_add_filter (dialog, code_filter);
}
gtk_file_chooser_set_filter (dialog, src? src_filter : code_filter);
gtk_window_set_title (GTK_WINDOW (dialog), title);
return dialog;
}
static void
get_file_ (file_callback_t callback,
const gchar *title,
gboolean is_src,
const gchar *def_file)
{
static gchar *last_folder = NULL;
if (callback != NULL)
{
GtkFileChooser *dialog = get_chooser_ (title, is_src);
if (def_file != NULL)
{
gtk_file_chooser_set_filename (dialog, def_file);
}
else if (last_folder != NULL)
{
gtk_file_chooser_set_current_folder (dialog, last_folder);
}
gint result = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_hide (GTK_WIDGET (dialog));
if (result == GTK_RESPONSE_ACCEPT)
{
gchar *filename = gtk_file_chooser_get_filename (dialog);
if (filename)
{
callback (filename);
if (last_folder) g_free (last_folder);
last_folder = g_path_get_dirname (filename);
g_free (filename);
}
}
}
}
/* exec prompt command */
static void
exec_cmd_ (mix_vm_command_t cmd, const gchar *arg)
{
gchar *command;
if (arg)
command = g_strdup_printf ("%s %s",
mix_vm_command_to_string (cmd),
arg);
else
command = g_strdup (mix_vm_command_to_string (cmd));
mixgtk_cmd_dispatcher_dispatch (command);
g_free (command);
}
/* load mix binary */
static void
open_cb_ (const gchar *file)
{
exec_cmd_ (MIX_CMD_LOAD, file);
}
void
on_file_open_activate (GtkWidget *w, gpointer data)
{
get_file_ (open_cb_, _("Load MIX program..."), FALSE, NULL);
}
/* edit mixal source */
static void
edit_cb_ (const gchar *file)
{
exec_cmd_ (MIX_CMD_EDIT, file);
}
void
on_file_edit_activate (GtkWidget *w, gpointer data)
{
get_file_ (edit_cb_,
_("Edit MIXAL source file..."),
TRUE,
mixgtk_cmd_dispatcher_get_src_path ());
}
/* compile mixal source */
static void
compile_cb_ (const gchar *file)
{
exec_cmd_ (MIX_CMD_COMPILE, file);
}
void
on_file_compile_activate (GtkWidget *w, gpointer data)
{
get_file_ (compile_cb_,
_("Compile MIXAL source file..."),
TRUE,
mixgtk_cmd_dispatcher_get_src_path ());
}
void
on_debug_run_activate (GtkWidget *w, gpointer p)
{
mixgtk_cmd_dispatcher_dispatch (mix_vm_command_to_string (MIX_CMD_RUN));
}
void
on_debug_next_activate (GtkWidget *w, gpointer p)
{
mixgtk_cmd_dispatcher_dispatch (mix_vm_command_to_string (MIX_CMD_NEXT));
}
void
on_file_exit_activate (GtkWidget *w, gpointer data)
{
gtk_main_quit ();
}
void
on_clear_breakpoints_activate (GtkWidget *w, gpointer data)
{
mixgtk_cmd_dispatcher_dispatch (mix_vm_command_to_string (MIX_CMD_CABP));
}
void
on_save_on_exit_toggle (GtkWidget *w, gpointer data)
{
gboolean active = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (w));
mixgtk_config_set_autosave (active);
}
void
on_save_activate (GtkWidget *w, gpointer data)
{
mixgtk_config_save ();
}
mdk-1.3.1/mixgtk/mixgtk_device.h 0000644 0001750 0001750 00000002511 12112755472 012253 /* -*-c-*- ---------------- mixgtk_device.h :
* Block devices used by mixgtk
* ------------------------------------------------------------------
* Copyright (C) 2001, 2004, 2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef MIXGTK_DEVICE_H
#define MIXGTK_DEVICE_H
#include
#include
#include
/* init default devices */
extern GtkWidget *
mixgtk_device_init (mix_vm_t *vm);
extern void
mixgtk_device_update_fonts (void);
/* change the output format of a device */
extern void
mixgtk_device_set_format (mix_device_type_t dev, gboolean dec);
#endif /* MIXGTK_DEVICE_H */
mdk-1.3.1/mixgtk/mixgtk_config.c 0000644 0001750 0001750 00000005635 12112755472 012266 /* -*-c-*- -------------- mixgtk_config.c :
* Implementation of the functions declared in mixgtk_config.h
* ------------------------------------------------------------------
* Copyright (C) 2001, 2002, 2004, 2006, 2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include
#include
#include
#include
#include
#include
#include "mixgtk.h"
#include "mixgtk_config.h"
static const gchar *MIXGTK_CONFIG_FILE_ = "gmixvm.config";
static const gchar *SHOW_TB_KEY_ = "Toolbars";
static const gchar *TB_YES_ = "Yes";
static const gchar *TB_NO_ = "No";
static const gchar *TB_STYLE_KEY_ = "ToolbarStyle";
static mix_config_t *config_ = NULL;
/* load configuration */
gboolean
mixgtk_config_load (void)
{
if (config_ == NULL)
{
gchar *cdir = g_strconcat (g_get_home_dir (), G_DIR_SEPARATOR_S,
MIXGTK_FILES_DIR, NULL);
config_ = mix_config_new (cdir, MIXGTK_CONFIG_FILE_);
g_free (cdir);
}
return (config_ != NULL);
}
/* get mixlib config */
mix_config_t *
mixgtk_config_get_mix_config (void)
{
return config_;
}
/* autosave state */
gboolean
mixgtk_config_is_autosave (void)
{
return mix_config_is_autosave (config_);
}
void
mixgtk_config_set_autosave (gboolean autosave)
{
mix_config_set_autosave (config_, autosave);
}
guint
mixgtk_config_tb_style (void)
{
return (guint)mix_config_get_integer (config_, TB_STYLE_KEY_);
}
void
mixgtk_config_set_tb_style (guint style)
{
mix_config_update_integer (config_, TB_STYLE_KEY_, (gint)style);
}
/* update config item */
void
mixgtk_config_update (const gchar *key, const gchar *value)
{
mix_config_update (config_, key, value);
}
/* get config item */
const gchar *
mixgtk_config_get (const gchar *key)
{
return mix_config_get (config_, key);
}
void
mixgtk_config_remove (const char *key)
{
mix_config_remove (config_, key);
}
/* save configuration */
void
mixgtk_config_save (void)
{
mix_config_save (config_);
}
gboolean
mixgtk_config_show_toolbars (void)
{
const gchar *show = mixgtk_config_get (SHOW_TB_KEY_);
return (!show || !strcmp (show, TB_YES_));
}
void
mixgtk_config_set_show_toolbars (gboolean show)
{
mixgtk_config_update (SHOW_TB_KEY_, show? TB_YES_ : TB_NO_);
}
mdk-1.3.1/mixgtk/mixgtk_cmd_dispatcher.h 0000644 0001750 0001750 00000003475 12112755472 013777 /* -*-c-*- ---------------- mixgtk_cmd_dispatcher.h :
* functions to access the command dispatcher
* ------------------------------------------------------------------
* Copyright (C) 2001, 2004, 2006, 2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef MIXGTK_CMD_DISPATCHER_H
#define MIXGTK_CMD_DISPATCHER_H
#include
#include
#include "mixgtk_widgets.h"
/* initialise the command dispatcher */
extern gboolean
mixgtk_cmd_dispatcher_init (mixgtk_dialog_id_t top);
extern void
mixgtk_cmd_dispatcher_update_fonts (void);
/* dispatch an externally provided command */
extern void
mixgtk_cmd_dispatcher_dispatch (const gchar *command);
/* get times */
extern void
mixgtk_cmd_dispatcher_get_times (gint *uptime, gint *progtime, gint *laptime);
/* get the underlying vm */
extern mix_vm_t *
mixgtk_cmd_dispatcher_get_vm (void);
/* get the current source file */
extern const gchar *
mixgtk_cmd_dispatcher_get_src_path (void);
/* get the mix cmd dispatcher */
extern mix_vm_cmd_dispatcher_t *
mixgtk_cmd_dispatcher_get_mix_dispatcher (void);
#endif /* MIXGTK_CMD_DISPATCHER_H */
mdk-1.3.1/mixgtk/mixgtk_cmd_dispatcher.c 0000644 0001750 0001750 00000031414 13743201230 013751 /* -*-c-*- -------------- mixgtk_cmd_dispatcher.c :
* Implementation of the functions declared in mixgtk_cmd_dispatcher.h
* ------------------------------------------------------------------
* Copyright (C) 2001, 2002, 2004, 2006, 2007, 2019 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include
#include
#include
#include
#include
#include
#include
#include
#ifdef HAVE_LIBHISTORY
# include
#endif
#ifdef MAKE_GUILE
# include
#endif
#include
#include
#include "mixgtk_mixvm.h"
#include "mixgtk_mixal.h"
#include "mixgtk_fontsel.h"
#include "mixgtk_config.h"
#include "mixgtk_external.h"
#include "mixgtk_cmd_dispatcher.h"
/* a mix vm command dispatcher */
typedef struct mixgtk_dispatch_
{
mix_vm_cmd_dispatcher_t *dispatcher; /* the underlying cmd dispatcher */
FILE *out; /* the dispatcher's output file */
int fildes[2]; /* pipe for communication with the dispatcher */
GtkWidget *prompt; /* the command prompt widget */
GtkWidget *log; /* the dispatcher's messages echo area */
GtkWidget *status; /* the status bar widget */
guint context; /* context of the status bar messages */
gchar *last_file;
} mixgtk_dispatch_data_t;
static struct mixgtk_dispatch_ dis_data_ = {NULL};
static const gchar *TITLE_FORMAT_ = "gmixvm - %s";
static void
log_command_ (mixgtk_dispatch_data_t *dis, const gchar *cmd)
{
GtkTextBuffer *buf = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dis->log));
GtkTextIter end;
gtk_text_buffer_get_end_iter (buf, &end);
gtk_text_buffer_place_cursor (buf, &end);
gtk_text_buffer_insert_at_cursor (buf, "MIX> ", -1);
gtk_text_buffer_insert_at_cursor (buf, cmd, -1);
gtk_text_buffer_insert_at_cursor (buf, "\n", -1);
#ifdef HAVE_LIBHISTORY
add_history ((char *)cmd);
/* history_search ((char *)cmd, 0); */
history_set_pos (history_base + history_length - 1);
#endif
}
static void
flush_log_ (mixgtk_dispatch_data_t *dis)
{
enum {BLKSIZE = 100};
static gchar BUFFER[BLKSIZE];
GtkTextBuffer *buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (dis->log));
GtkTextMark *mark;
GtkTextIter end;
ssize_t k;
gtk_text_buffer_get_end_iter (buffer, &end);
gtk_text_buffer_place_cursor (buffer, &end);
fflush (dis->out);
while ((k = read (dis->fildes[0], BUFFER, BLKSIZE)) != 0)
{
if (k == -1 && errno != EINTR) break;
if (k != -1)
gtk_text_buffer_insert_at_cursor (buffer, BUFFER, k);
}
mark = gtk_text_buffer_get_insert (buffer);
gtk_text_view_scroll_to_mark (GTK_TEXT_VIEW (dis->log), mark, 0,
TRUE, 0, 0);
}
/* hooks */
static void
global_post_hook_ (mix_vm_cmd_dispatcher_t *dis,
mix_vm_command_t cmd, const gchar *arg, gpointer data)
{
flush_log_ ((mixgtk_dispatch_data_t *)data);
mixgtk_mixvm_update_vm_widgets ();
}
static void
load_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,
gpointer data)
{
static glong id = -1;
if (mix_vm_cmd_dispatcher_get_last_result (dis))
{
GtkWindow *mainw =
GTK_WINDOW (mixgtk_widget_factory_get_dialog (MIXGTK_MAIN));
if (dis_data_.last_file) g_free (dis_data_.last_file);
dis_data_.last_file = g_strdup_printf (TITLE_FORMAT_, arg);
gtk_window_set_title (mainw, dis_data_.last_file);
mixgtk_mixal_load_file ();
mixgtk_mixal_update ();
mixgtk_mixal_update_bp_all ();
if (id != -1)
gtk_statusbar_remove (GTK_STATUSBAR (dis_data_.status),
dis_data_.context, (guint)id);
id =
gtk_statusbar_push (GTK_STATUSBAR (dis_data_.status), dis_data_.context,
dis_data_.last_file);
}
}
static void
run_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,
gpointer data)
{
mixgtk_mixal_update ();
}
static void
next_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,
gpointer data)
{
mixgtk_mixal_update ();
}
static void
linebp_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,
gpointer data)
{
if (arg && strlen (arg)) mixgtk_mixal_update_bp_at_line (atoi (arg));
}
static void
addrbp_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,
gpointer data)
{
if (arg && strlen (arg)) mixgtk_mixal_update_bp_at_address (atoi (arg));
}
static void
allbp_post_hook_ (mix_vm_cmd_dispatcher_t *dis, const gchar *arg,
gpointer data)
{
mixgtk_mixal_update_bp_all ();
}
static void
install_hooks_ (void)
{
mix_vm_cmd_dispatcher_global_post_hook (dis_data_.dispatcher,
global_post_hook_,
(gpointer)(&dis_data_));
mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
MIX_CMD_LOAD, load_post_hook_,
NULL);
mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
MIX_CMD_RUN, run_post_hook_,
NULL);
mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
MIX_CMD_NEXT, next_post_hook_,
NULL);
mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
MIX_CMD_SBP, linebp_post_hook_,
NULL);
mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
MIX_CMD_CBP, linebp_post_hook_,
NULL);
mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
MIX_CMD_SBPA, addrbp_post_hook_,
NULL);
mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
MIX_CMD_CBPA, addrbp_post_hook_,
NULL);
mix_vm_cmd_dispatcher_post_hook (dis_data_.dispatcher,
MIX_CMD_CABP, allbp_post_hook_,
NULL);
}
/* initialise the command dispatcher */
gboolean
mixgtk_cmd_dispatcher_init (mixgtk_dialog_id_t top)
{
static gboolean restart = FALSE;
gchar *text = NULL;
dis_data_.prompt =
mixgtk_widget_factory_get (top, MIXGTK_WIDGET_PROMPT);
g_return_val_if_fail (dis_data_.prompt != NULL, FALSE);
if (dis_data_.log)
text = gtk_editable_get_chars (GTK_EDITABLE (dis_data_.log), 0, -1);
dis_data_.log =
mixgtk_widget_factory_get (top, MIXGTK_WIDGET_LOG);
g_return_val_if_fail (dis_data_.log != NULL, FALSE);
if (text)
{
gtk_text_buffer_insert_at_cursor
(gtk_text_view_get_buffer (GTK_TEXT_VIEW (dis_data_.log)), text, -1);
g_free (text);
}
if (!dis_data_.dispatcher)
{
static const gchar *HISTORY_FILE = "gmixvm.history";
static gint HISTORY_SIZE = 100;
mix_config_t *config = mixgtk_config_get_mix_config ();
int r = pipe (dis_data_.fildes);
g_return_val_if_fail (r == 0, FALSE);
/* connect stdout/stderr to the pipe's write end */
if (dup2 (dis_data_.fildes[1], STDOUT_FILENO) == -1
|| dup2 (dis_data_.fildes[1], STDOUT_FILENO) == -1)
return FALSE;
dis_data_.out = fdopen (dis_data_.fildes[1], "w");
g_return_val_if_fail (dis_data_.out != NULL, FALSE);
r = fcntl (dis_data_.fildes[0], F_GETFL, 0);
g_return_val_if_fail (r != -1, FALSE);
r |= O_NONBLOCK;
r = fcntl(dis_data_.fildes[0], F_SETFL, r);
g_return_val_if_fail (r != -1, FALSE);
if (!mix_config_get_history_file (config))
mix_config_set_history_file (config, HISTORY_FILE);
if (mix_config_get_history_size (config) == 0)
mix_config_set_history_size (config, HISTORY_SIZE);
dis_data_.dispatcher =
mix_vm_cmd_dispatcher_new_with_config (dis_data_.out,
dis_data_.out,
config);
mix_vm_cmd_dispatcher_print_time (dis_data_.dispatcher, FALSE);
install_hooks_ ();
}
dis_data_.status =
mixgtk_widget_factory_get (MIXGTK_MAIN, MIXGTK_WIDGET_STATUSBAR);
g_return_val_if_fail (dis_data_.status != NULL, FALSE);
dis_data_.context = gtk_statusbar_get_context_id (GTK_STATUSBAR
(dis_data_.status),
"cmd_dis_context");
if (!restart) mixgtk_external_init (dis_data_.dispatcher);
if (dis_data_.last_file)
gtk_window_set_title
(GTK_WINDOW (mixgtk_widget_factory_get_dialog (MIXGTK_MAIN)),
dis_data_.last_file);
mixgtk_fontsel_set_font (MIX_FONT_LOG, dis_data_.log);
mixgtk_fontsel_set_font (MIX_FONT_PROMPT, dis_data_.prompt);
restart = TRUE;
return TRUE;
}
/* dispatch an externally provided command */
#ifdef MAKE_GUILE
static gboolean
try_guile_ (const gchar *command)
{
if (command && command[0] == '(' && command[strlen (command) - 1] == ')')
{
mixguile_interpret_command (command);
return TRUE;
}
return FALSE;
}
#else
# define try_guile_(ignored) FALSE
#endif
void
mixgtk_cmd_dispatcher_dispatch (const gchar *command)
{
GtkWidget *entry = dis_data_.prompt;
g_return_if_fail (command != NULL);
g_assert (entry != NULL);
gtk_entry_set_text (GTK_ENTRY (entry), command);
log_command_ (&dis_data_, command);
if (!try_guile_ (command))
mix_vm_cmd_dispatcher_dispatch_text (dis_data_.dispatcher, command);
gtk_entry_set_text (GTK_ENTRY (entry), "");
}
/* get times */
void
mixgtk_cmd_dispatcher_get_times (gint *uptime, gint *progtime, gint *laptime)
{
if (uptime != NULL)
*uptime = mix_vm_cmd_dispatcher_get_uptime (dis_data_.dispatcher);
if (progtime != NULL)
*progtime = mix_vm_cmd_dispatcher_get_progtime (dis_data_.dispatcher);
if (laptime != NULL)
*laptime = mix_vm_cmd_dispatcher_get_laptime (dis_data_.dispatcher);
}
/* get the underlying vm */
mix_vm_t *
mixgtk_cmd_dispatcher_get_vm (void)
{
return (mix_vm_t *) mix_vm_cmd_dispatcher_get_vm (dis_data_.dispatcher);
}
/* get the current source file */
const gchar *
mixgtk_cmd_dispatcher_get_src_path (void)
{
return mix_vm_cmd_dispatcher_get_src_file_path (dis_data_.dispatcher);
}
/* get the mix cmd dispatcher */
mix_vm_cmd_dispatcher_t *
mixgtk_cmd_dispatcher_get_mix_dispatcher (void)
{
return dis_data_.dispatcher;
}
/* process commands */
void
complete_command_ (void)
{
GtkEntry *entry = GTK_ENTRY (dis_data_.prompt);
gchar *prefix = NULL;
const gchar *text = gtk_entry_get_text (entry);
const GList *cmds =
mix_vm_cmd_dispatcher_complete (dis_data_.dispatcher, text, &prefix);
if (prefix != NULL)
{
GtkTextBuffer *buf =
gtk_text_view_get_buffer (GTK_TEXT_VIEW (dis_data_.log));
gtk_entry_set_text (entry, prefix);
if (g_list_length ((GList *)cmds) > 1)
{
static gchar BUFFER[25];
gint k = 0;
gtk_text_buffer_insert_at_cursor (buf, "Completions:\n", -1);
while (cmds)
{
g_snprintf (BUFFER, 25, "%-12s", (const char*)cmds->data);
++k;
gtk_text_buffer_insert_at_cursor (buf, BUFFER, -1);
if (k%5 == 0)
gtk_text_buffer_insert_at_cursor (buf, "\n", -1);
cmds = cmds->next;
}
if (k%5 != 0)
gtk_text_buffer_insert_at_cursor (buf, "\n", -1);
}
else
{
gint pos = strlen (prefix);
gtk_editable_insert_text (GTK_EDITABLE (entry), " ", 1, &pos);
}
flush_log_ (&dis_data_);
g_free (prefix);
}
}
int
on_command_prompt_key_press_event (GtkEntry *w, GdkEventKey *e, gpointer d)
{
guint key = e->keyval;
gboolean result = FALSE;
#ifdef HAVE_LIBHISTORY
HIST_ENTRY *entry = NULL;
if (key == GDK_KEY_Up)
{
entry = previous_history ();
if (entry && entry->line)
gtk_entry_set_text (w, entry->line);
result = TRUE;
}
if (key == GDK_KEY_Down)
{
entry = next_history ();
if (entry && entry->line)
gtk_entry_set_text (w, entry->line);
result = TRUE;
}
#endif
if (key == GDK_KEY_Tab)
{
complete_command_ ();
result = TRUE;
}
if (result) gtk_editable_set_position (GTK_EDITABLE (w), -1);
return result;
}
void
on_command_prompt_activate (GtkEntry *prompt, gpointer data)
{
gchar *text =
g_strstrip (gtk_editable_get_chars (GTK_EDITABLE (prompt), 0, -1));
if (text && *text)
{
log_command_ (&dis_data_, text);
if (!try_guile_ (text))
mix_vm_cmd_dispatcher_dispatch_text (dis_data_.dispatcher, text);
gtk_entry_set_text (prompt, "");
}
g_free (text);
}
void
on_log_font_activate ()
{
GtkWidget *w[] = { dis_data_.log };
mixgtk_fontsel_query_font (MIX_FONT_LOG, w, 1);
}
void
on_prompt_font_activate ()
{
GtkWidget *w[] = { dis_data_.prompt };
mixgtk_fontsel_query_font (MIX_FONT_PROMPT, w, 1);
}
void
mixgtk_cmd_dispatcher_update_fonts (void)
{
mixgtk_fontsel_set_font (MIX_FONT_LOG, dis_data_.log);
mixgtk_fontsel_set_font (MIX_FONT_PROMPT, dis_data_.prompt);
}
mdk-1.3.1/mixgtk/mixgtk_wm.h 0000644 0001750 0001750 00000002432 12112755472 011441 /* -*-c-*- ---------------- mixgtk_wm.h :
* Functions for window management
* ------------------------------------------------------------------
* Copyright (C) 2001, 2004, 2006, 2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef MIXGTK_WM_H
#define MIXGTK_WM_H
#include "mixgtk.h"
typedef enum {
MIXGTK_MIXVM_WINDOW,
MIXGTK_MIXAL_WINDOW,
MIXGTK_DEVICES_WINDOW
} mixgtk_window_id_t;
extern gboolean
mixgtk_wm_init (void);
extern void
mixgtk_wm_attach_window (mixgtk_window_id_t w);
extern void
mixgtk_wm_detach_window (mixgtk_window_id_t w);
#endif /* MIXGTK_WM_H */
mdk-1.3.1/mixgtk/mixgtk_wm.c 0000644 0001750 0001750 00000042513 13743201230 011425 /* -*-c-*- -------------- mixgtk_wm.c :
* Implementation of the functions declared in mixgtk_wm.h
* ------------------------------------------------------------------
* Copyright (C) 2001, 2002, 2004, 2006, 2007, 2008, 2019, 2020 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include
#include "mixgtk_wm.h"
#include "mixgtk_config.h"
#include "mixgtk_device.h"
#include "mixgtk_mixvm.h"
#include "mixgtk_mixal.h"
#include "mixgtk_widgets.h"
#include "mixgtk_cmd_dispatcher.h"
#include "mixgtk_gen_handlers.h"
#include "mixgtk.h"
typedef struct window_info_t_
{
mixgtk_dialog_id_t dialog;
GtkWidget *widget;
GtkCheckMenuItem *menu;
const gchar *menu_name;
const gchar *config_key;
const gchar *toolbar_name;
const gchar *attach_button;
gboolean detached;
void (*detach) (void);
void (*attach) (void);
} window_info_t_;
static const gchar *DETACH_YES_ = "Yes";
static const gchar *DETACH_NO_ = "No";
static GtkWidget *about_ = NULL;
static GtkContainer *mixvm_container_ = NULL;
static GtkContainer *mixal_container_ = NULL;
static GtkContainer *dev_container_ = NULL;
static GtkToolItem *attach_button_ = NULL;
static GtkToolItem *detach_button_ = NULL;
static const gchar *TB_MENU_NAME_ = "show_toolbars";
static GtkCheckMenuItem *tb_menu_ = NULL;
static GtkNotebook *notebook_ = NULL;
static mix_vm_t *vm_ = NULL;
static void init_info_ (void);
static void init_notebook_ (void);
static void init_dispatcher_ (void);
static void init_mixvm_ (void);
static void init_mixal_ (void);
static void init_dev_ (void);
static void init_signals_ (void);
static void init_visibility_ (void);
static void init_tb_ (void);
static void init_about_ (void);
static void init_autosave_ (void);
static void set_tb_style_ (guint style);
static void show_toolbars_ (gboolean show);
static void add_page_ (GtkWidget *w, mixgtk_window_id_t id);
static void mixvm_attach_ (void);
static void mixvm_detach_ (void);
static void mixal_attach_ (void);
static void mixal_detach_ (void);
static void dev_attach_ (void);
static void dev_detach_ (void);
static void reparent_ (GtkWidget *widget, GtkWidget *parent);
static void update_attach_buttons_ (void);
static void on_tb_style_ (GtkMenuItem *w, gpointer style);
static void on_nb_switch_ (GtkNotebook *notebook, GtkWidget *page,
guint page_num, gpointer user_data);
static window_info_t_ infos_[] = {
{MIXGTK_MIXVM_DIALOG, NULL, NULL,
"detach_vm", "MIX.detach", "mixvm_toolbar", "attach_button_mixvm",
FALSE, mixvm_detach_, mixvm_attach_},
{MIXGTK_MIXAL_DIALOG, NULL, NULL,
"detach_source", "MIXAL.detach", "mixal_toolbar", "attach_button_mixal",
FALSE, mixal_detach_, mixal_attach_},
{MIXGTK_DEVICES_DIALOG, NULL, NULL,
"detach_dev", "Devices.detach", "dev_toolbar", "attach_button_dev",
FALSE, dev_detach_, dev_attach_}
};
static size_t INF_NO_ = sizeof (infos_) / sizeof (infos_[0]);
gboolean
mixgtk_wm_init (void)
{
gint k;
init_info_ ();
init_notebook_ ();
init_dispatcher_ ();
init_mixvm_ ();
init_mixal_ ();
init_dev_ ();
init_tb_ ();
for (k = 0; k < INF_NO_; ++k)
{
if (infos_[k].detached)
mixgtk_wm_detach_window (k);
else
mixgtk_wm_attach_window (k);
}
init_about_ ();
init_autosave_ ();
init_visibility_ ();
init_signals_ ();
return TRUE;
}
void
mixgtk_wm_detach_window (mixgtk_window_id_t w)
{
if (w < INF_NO_)
{
(*(infos_[w].detach)) ();
infos_[w].detached = TRUE;
gtk_check_menu_item_set_active (infos_[w].menu, TRUE);
mixgtk_config_update (infos_[w].config_key, DETACH_YES_);
if (infos_[w].widget != NULL) gtk_widget_show (infos_[w].widget);
if (gtk_notebook_get_n_pages (notebook_) < 1)
gtk_widget_hide (GTK_WIDGET (notebook_));
gtk_widget_show (mixgtk_widget_factory_get_dialog (infos_[w].dialog));
update_attach_buttons_ ();
}
}
void
mixgtk_wm_attach_window (mixgtk_window_id_t w)
{
if (w < INF_NO_)
{
gint page = gtk_notebook_page_num (notebook_, infos_[w].widget);
gtk_widget_hide (mixgtk_widget_factory_get_dialog (infos_[w].dialog));
if (page < 0) (*(infos_[w].attach)) ();
infos_[w].detached = FALSE;
gtk_check_menu_item_set_active (infos_[w].menu, FALSE);
mixgtk_config_update (infos_[w].config_key, DETACH_NO_);
if (gtk_notebook_get_n_pages (notebook_) == 1)
gtk_widget_show (GTK_WIDGET (notebook_));
update_attach_buttons_ ();
}
}
/* callbacks */
void
on_detach_clicked (GtkWidget *ignored)
{
gint page = gtk_notebook_get_current_page (notebook_);
if (page >= 0)
{
gint k;
GtkWidget *w = gtk_notebook_get_nth_page (notebook_, page);
for (k = 0; k < INF_NO_; ++k)
if (infos_[k].widget == w) mixgtk_wm_detach_window (k);
}
}
void
on_attach_all_clicked ()
{
gint k;
for (k = INF_NO_; k > 0; --k)
if (infos_[k - 1].detached) mixgtk_wm_attach_window (k - 1);
}
void
on_attach_toggled (GtkCheckMenuItem *item)
{
gint k;
for (k = 0; k < INF_NO_; ++k)
if (item == infos_[k].menu) break;
g_return_if_fail (k < INF_NO_);
gboolean active = gtk_check_menu_item_get_active (item);
if (active) mixgtk_wm_detach_window (k);
else mixgtk_wm_attach_window (k);
mixgtk_config_update (infos_[k].config_key, active? DETACH_YES_ : DETACH_NO_);
}
void
on_window_hide (GtkWidget *w)
{
gint k;
for (k = 0; k < INF_NO_; ++k)
if (w == mixgtk_widget_factory_get_dialog (infos_[k].dialog)) break;
g_return_if_fail (k < INF_NO_);
mixgtk_wm_attach_window (k);
}
void
on_show_toolbars_toggled (GtkCheckMenuItem *item)
{
gboolean active = gtk_check_menu_item_get_active (item);
if (active != mixgtk_config_show_toolbars ()) show_toolbars_ (active);
}
void
on_widget_attach (GtkWidget *ign, gpointer id)
{
mixgtk_wm_attach_window (GPOINTER_TO_INT (id));
}
/* about box */
void
on_about_activate (GtkWidget *w, gpointer data)
{
if (!about_) init_about_ ();
gtk_widget_show (about_);
}
void
on_about_clicked (GtkWidget *w)
{
if (about_) gtk_widget_hide (about_);
}
static void
init_info_ (void)
{
gint k;
for (k = 0; k < INF_NO_; ++k)
{
const gchar *txt;
infos_[k].menu =
GTK_CHECK_MENU_ITEM
(mixgtk_widget_factory_get_by_name (infos_[k].menu_name));
g_assert (infos_[k].menu != NULL);
txt = mixgtk_config_get (infos_[k].config_key);
infos_[k].detached = txt && !g_ascii_strcasecmp (txt, DETACH_YES_);
}
}
static void
init_notebook_ (void)
{
notebook_ =
GTK_NOTEBOOK (mixgtk_widget_factory_get (MIXGTK_MAIN,
MIXGTK_WIDGET_NOTEBOOK));
g_assert (notebook_ != NULL);
gtk_widget_show (GTK_WIDGET (notebook_));
}
static void
add_page_ (GtkWidget *page, mixgtk_window_id_t id)
{
static const gchar *LABELS[] = {
N_("_Virtual machine"), N_("_Source"), N_("_Devices")
};
gint p = 0;
g_assert (page != NULL);
g_assert (id < INF_NO_);
g_assert (notebook_ != NULL);
if (id > MIXGTK_MIXVM_WINDOW)
{
if (id == MIXGTK_DEVICES_WINDOW)
p = gtk_notebook_get_n_pages (notebook_);
else
p = infos_[MIXGTK_MIXVM_WINDOW].detached ? 0 : 1;
}
gtk_notebook_insert_page (notebook_, page,
gtk_label_new_with_mnemonic (LABELS[id]),
p);
gtk_notebook_set_current_page (notebook_, p);
gtk_widget_show (page);
gtk_widget_show (GTK_WIDGET (notebook_));
}
static void
init_signals_ (void)
{
gint k;
for (k = 0; k < INF_NO_; ++k)
{
GObject *dialog =
G_OBJECT (mixgtk_widget_factory_get_dialog (infos_[k].dialog));
GObject *button =
G_OBJECT (mixgtk_widget_factory_get_by_name (infos_[k].attach_button));
g_assert (dialog != NULL);
g_assert (button != NULL);
g_signal_connect (button, "clicked",
G_CALLBACK (on_widget_attach), GINT_TO_POINTER (k));
g_signal_connect (dialog, "destroy",
G_CALLBACK (on_window_hide), NULL);
g_signal_connect (dialog, "destroy_event",
G_CALLBACK (on_window_hide), NULL);
g_signal_connect (dialog, "delete_event",
G_CALLBACK (on_window_hide), NULL);
g_signal_connect (G_OBJECT (infos_[k].menu), "toggled",
G_CALLBACK (on_attach_toggled), NULL);
}
GtkWindow *mainw =
GTK_WINDOW (mixgtk_widget_factory_get_dialog (MIXGTK_MAIN));
g_signal_connect (mainw, "destroy",
G_CALLBACK (on_file_exit_activate), NULL);
}
static void
init_visibility_ (void)
{
gint k;
for (k = 0; k < INF_NO_; ++k)
if (infos_[k].detached)
gtk_widget_show (mixgtk_widget_factory_get_dialog (infos_[k].dialog));
if (gtk_notebook_get_n_pages (notebook_) > 0)
gtk_notebook_set_current_page (notebook_, 0);
gtk_widget_show (mixgtk_widget_factory_get_dialog (MIXGTK_MAIN));
}
static void
init_dispatcher_ (void)
{
if (!mixgtk_cmd_dispatcher_init (MIXGTK_MAIN))
g_assert (FALSE);
vm_ = mixgtk_cmd_dispatcher_get_vm ();
g_assert (vm_ != NULL);
}
static void
init_mixvm_ (void)
{
GtkContainer *vm =
GTK_CONTAINER
(mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG, MIXGTK_WIDGET_MIXVM));
mixvm_container_ =
GTK_CONTAINER (mixgtk_widget_factory_get (MIXGTK_MIXVM_DIALOG,
MIXGTK_WIDGET_MIXVM_CONTAINER));
g_assert (mixvm_container_ != NULL);
g_assert (vm != NULL);
g_object_ref (G_OBJECT (vm));
infos_[MIXGTK_MIXVM_WINDOW].widget = GTK_WIDGET (vm);
mixgtk_mixvm_init (vm_);
mixgtk_mixvm_update_vm_widgets ();
gtk_widget_show (GTK_WIDGET (vm));
}
static void
init_mixal_ (void)
{
GtkWidget *page = gtk_scrolled_window_new (NULL, NULL);
GtkWidget *mixal = mixgtk_mixal_init (vm_);
g_assert (page != NULL);
g_assert (mixal != NULL);
g_object_ref (page);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (page),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (page), mixal);
infos_[MIXGTK_MIXAL_WINDOW].widget = page;
mixal_container_ =
GTK_CONTAINER (mixgtk_widget_factory_get (MIXGTK_MIXAL_DIALOG,
MIXGTK_WIDGET_MIXAL_CONTAINER));
g_assert (mixal_container_ != NULL);
gtk_container_add (mixal_container_, page);
gtk_widget_show (mixal);
gtk_widget_show (page);
gtk_widget_show (GTK_WIDGET (mixal_container_));
}
static void
init_dev_ (void)
{
GtkWidget *page = gtk_scrolled_window_new (NULL, NULL);
GtkWidget *devs = mixgtk_device_init (vm_);
g_assert (page != NULL);
g_assert (devs != NULL);
g_object_ref (page);
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (page),
GTK_POLICY_AUTOMATIC,
GTK_POLICY_AUTOMATIC);
gtk_container_add (GTK_CONTAINER (page), devs);
infos_[MIXGTK_DEVICES_WINDOW].widget = page;
dev_container_ =
GTK_CONTAINER (mixgtk_widget_factory_get (MIXGTK_DEVICES_DIALOG,
MIXGTK_WIDGET_DEV_CONTAINER));
g_assert (dev_container_ != NULL);
gtk_container_add (dev_container_, page);
gtk_widget_show (devs);
gtk_widget_show (page);
}
static void
init_tb_ (void)
{
gchar *names[4];
gint k;
gint style = mixgtk_config_tb_style ();
tb_menu_ = GTK_CHECK_MENU_ITEM
(mixgtk_widget_factory_get_by_name (TB_MENU_NAME_));
g_assert (tb_menu_ != NULL);
gtk_check_menu_item_set_active (tb_menu_, mixgtk_config_show_toolbars ());
show_toolbars_ (mixgtk_config_show_toolbars ());
g_signal_connect (G_OBJECT (tb_menu_), "toggled",
G_CALLBACK (on_show_toolbars_toggled), NULL);
attach_button_ = GTK_TOOL_ITEM
(mixgtk_widget_factory_get (MIXGTK_MAIN, MIXGTK_WIDGET_ATTACH_BUTTON));
detach_button_ = GTK_TOOL_ITEM
(mixgtk_widget_factory_get (MIXGTK_MAIN, MIXGTK_WIDGET_DETACH_BUTTON));
g_assert (attach_button_);
g_assert (detach_button_);
names[GTK_TOOLBAR_ICONS] = "tb_style_icons";
names[GTK_TOOLBAR_TEXT] = "tb_style_labels";
names[GTK_TOOLBAR_BOTH] = "tb_style_both";
names[GTK_TOOLBAR_BOTH_HORIZ] = "tb_style_bothh";
for (k = 0; k < 4; ++k)
{
GtkWidget *item = mixgtk_widget_factory_get_by_name (names[k]);
g_signal_connect (G_OBJECT (item),
"activate",
G_CALLBACK (on_tb_style_), GUINT_TO_POINTER (k));
gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (item), (k == style));
}
set_tb_style_ (style);
}
static void
on_tb_style_ (GtkMenuItem *w, gpointer style)
{
guint ui_style = GPOINTER_TO_UINT (style);
set_tb_style_ (ui_style);
mixgtk_config_set_tb_style (ui_style);
}
static const gchar *TB_NAME = "main_toolbar";
static void
set_tb_style_ (guint style)
{
gint k;
GtkToolbar *tb =
GTK_TOOLBAR (mixgtk_widget_factory_get_by_name (TB_NAME));
gtk_toolbar_set_style (tb, style);
for (k = 0; k < INF_NO_; ++k)
{
GtkToolbar *tb = GTK_TOOLBAR
(mixgtk_widget_factory_get_by_name (infos_[k].toolbar_name));
gtk_toolbar_set_style (tb, style);
}
}
static void
show_toolbars_ (gboolean show)
{
gint k;
GtkWidget *handle = mixgtk_widget_factory_get_by_name (TB_NAME);
if (show)
gtk_widget_show (handle);
else
gtk_widget_hide (handle);
for (k = 0; k < INF_NO_; ++k)
{
GtkWidget *hd =
mixgtk_widget_factory_get_by_name (infos_[k].toolbar_name);
if (show) gtk_widget_show (hd); else gtk_widget_hide (hd);
}
mixgtk_config_set_show_toolbars (show);
}
static void
init_autosave_ (void)
{
#define AUTOSAVE_ITEM_ "save_on_exit"
GtkCheckMenuItem *item = GTK_CHECK_MENU_ITEM
(mixgtk_widget_factory_get_by_name (AUTOSAVE_ITEM_));
if (item)
{
gtk_check_menu_item_set_active (item, mixgtk_config_is_autosave ());
}
}
static void
init_about_ (void)
{
#define VERSION_LABEL_ "version_label"
#define GPL_TEXT_ "gpl_text"
GtkWidget *label;
about_ = mixgtk_widget_factory_get_dialog (MIXGTK_ABOUT_DIALOG);
g_assert (about_ != NULL);
label = mixgtk_widget_factory_get_by_name (VERSION_LABEL_);
g_assert (label != NULL);
gtk_label_set_text (GTK_LABEL (label), VERSION);
gtk_widget_show (label);
}
static void
mixvm_attach_ (void)
{
gtk_container_remove (mixvm_container_, infos_[MIXGTK_MIXVM_WINDOW].widget);
add_page_ (infos_[MIXGTK_MIXVM_WINDOW].widget, MIXGTK_MIXVM_WINDOW);
}
static void
reparent_ (GtkWidget *widget, GtkWidget *parent)
{
gtk_container_remove (GTK_CONTAINER (gtk_widget_get_parent (widget)), widget);
gtk_container_add (GTK_CONTAINER (parent), widget);
}
static void
mixvm_detach_ (void)
{
reparent_ (infos_[MIXGTK_MIXVM_WINDOW].widget, GTK_WIDGET (mixvm_container_));
}
static void
mixal_attach_ (void)
{
static GtkStatusbar *stat = NULL;
if (stat == NULL)
{
stat =
GTK_STATUSBAR
(mixgtk_widget_factory_get (MIXGTK_MAIN, MIXGTK_WIDGET_STATUSBAR));
g_assert (stat);
g_signal_connect (G_OBJECT (notebook_), "switch-page",
G_CALLBACK (on_nb_switch_), NULL);
}
mixgtk_mixal_reparent (stat);
gtk_container_remove (mixal_container_, infos_[MIXGTK_MIXAL_WINDOW].widget);
add_page_ (infos_[MIXGTK_MIXAL_WINDOW].widget, MIXGTK_MIXAL_WINDOW);
}
static void
mixal_detach_ (void)
{
static GtkStatusbar *stat = NULL;
if (stat == NULL)
{
stat =
GTK_STATUSBAR
(mixgtk_widget_factory_get (MIXGTK_MIXAL_DIALOG,
MIXGTK_WIDGET_MIXAL_STATUSBAR));
g_assert (stat);
}
mixgtk_mixal_reparent (stat);
reparent_ (infos_[MIXGTK_MIXAL_WINDOW].widget, GTK_WIDGET (mixal_container_));
}
static void
dev_attach_ (void)
{
gtk_container_remove (dev_container_, infos_[MIXGTK_DEVICES_WINDOW].widget);
add_page_ (infos_[MIXGTK_DEVICES_WINDOW].widget, MIXGTK_DEVICES_WINDOW);
}
static void
dev_detach_ (void)
{
reparent_ (infos_[MIXGTK_DEVICES_WINDOW].widget, GTK_WIDGET (dev_container_));
}
static void
on_nb_switch_ (GtkNotebook *notebook, GtkWidget *page,
guint page_num, gpointer user_data)
{
if (!(infos_[MIXGTK_MIXAL_WINDOW].detached)
&& (page != infos_[MIXGTK_MIXAL_WINDOW].widget))
mixgtk_mixal_pop_status ();
}
static void
update_attach_buttons_ (void)
{
gint k;
gboolean wants_attach = FALSE;
gboolean wants_detach = FALSE;
g_assert (attach_button_);
g_assert (detach_button_);
for (k = 0; k < INF_NO_; ++k)
{
wants_attach = wants_attach || infos_[k].detached;
wants_detach = wants_detach || !infos_[k].detached;
}
gtk_tool_item_set_visible_horizontal (attach_button_, wants_attach);
gtk_tool_item_set_visible_vertical (attach_button_, wants_attach);
gtk_tool_item_set_visible_horizontal (detach_button_, wants_detach);
gtk_tool_item_set_visible_vertical (detach_button_, wants_detach);
}
mdk-1.3.1/mixgtk/mixgtk_config.h 0000644 0001750 0001750 00000003653 12112755472 012271 /* -*-c-*- ---------------- mixgtk_config.h :
* Configuration functions declarations.
* ------------------------------------------------------------------
* Copyright (C) 2001, 2004, 2006, 2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef MIXGTK_CONFIG_H
#define MIXGTK_CONFIG_H
#include
#include
/* load configuration */
extern gboolean
mixgtk_config_load (void);
/* get mix config */
extern mix_config_t *
mixgtk_config_get_mix_config (void);
/* autosave state */
extern gboolean
mixgtk_config_is_autosave (void);
extern void
mixgtk_config_set_autosave (gboolean autosave);
/* toolbar style */
extern guint
mixgtk_config_tb_style (void);
extern void
mixgtk_config_set_tb_style (guint style);
/* update config item */
extern void
mixgtk_config_update (const gchar *key, const gchar *value);
/* get config item */
extern const gchar *
mixgtk_config_get (const gchar *key);
/* remove config item */
extern void
mixgtk_config_remove (const gchar *key);
/* save configuration */
extern void
mixgtk_config_save (void);
/* shared config params */
extern gboolean
mixgtk_config_show_toolbars (void);
extern void
mixgtk_config_set_show_toolbars (gboolean show);
#endif /* MIXGTK_CONFIG_H */
mdk-1.3.1/mixgtk/mixgtk_fontsel.h 0000644 0001750 0001750 00000002732 12112755472 012473 /* -*-c-*- ---------------- mixgtk_fontsel.h :
* Functions for handling font selection.
* ------------------------------------------------------------------
* Copyright (C) 2001, 2004, 2006, 2007, 2008 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef MIXGTK_FONTSEL_H
#define MIXGTK_FONTSEL_H
#include
#include "mixgtk_widgets.h"
typedef enum {
MIX_FONT_MIXVM,
MIX_FONT_LOG,
MIX_FONT_PROMPT,
MIX_FONT_MIXAL,
MIX_FONT_DEVICES,
MIX_FONT_SYMBOLS,
MIX_FONT_DEFAULT,
MIX_FONT_NO
} mixgtk_font_t;
/* configured fonts */
extern void
mixgtk_fontsel_set_font (mixgtk_font_t f, GtkWidget *w);
extern gboolean
mixgtk_fontsel_query_font (mixgtk_font_t f, GtkWidget **ws, size_t no);
extern void
on_all_fonts_activate (void);
#endif /* MIXGTK_FONTSEL_H */
mdk-1.3.1/mixgtk/mixgtk_widgets.h 0000644 0001750 0001750 00000006153 13743201230 012455 /* -*-c-*- ---------------- mixgtk_widgets.h :
* glade-based factory of mixvm widgets
* ------------------------------------------------------------------
* Copyright (C) 2001, 2004, 2006, 2007, 2019, 2020 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef MIXGTK_WIDGETS_H
#define MIXGTK_WIDGETS_H
#include
#include
/* enumeration of gmixvm dialogs */
typedef enum {
MIXGTK_MAIN, /* main app window */
MIXGTK_MIXVM_DIALOG, /* mixvm dialog */
MIXGTK_MIXAL_DIALOG, /* mixal dialog */
MIXGTK_DEVICES_DIALOG, /* devices dialog */
MIXGTK_WORD_DIALOG, /* input dialog for a mix word */
MIXGTK_ABOUT_DIALOG,
MIXGTK_GOTO_DIALOG,
MIXGTK_FONTSEL_DIALOG, /* font selection dialog */
MIXGTK_DEVFORM_DIALOG, /* device format config dialog */
MIXGTK_EXTERNPROG_DIALOG, /* external programs dialog */
MIXGTK_SYMBOLS_DIALOG, /* symbol table dialog */
MIXGTK_INPUT_DIALOG, /* console input dialog */
MIXGTK_DEVDIR_DIALOG /* devices directory chooser */
} mixgtk_dialog_id_t;
/* enumeration of mixvm widget ids */
typedef enum {
MIXGTK_WIDGET_STATUSBAR,
MIXGTK_WIDGET_ATTACH_BUTTON,
MIXGTK_WIDGET_DETACH_BUTTON,
MIXGTK_WIDGET_NOTEBOOK, /* the notebook */
MIXGTK_WIDGET_MIXVM, /* virtual machine */
MIXGTK_WIDGET_MIXVM_CONTAINER,
MIXGTK_WIDGET_PROMPT, /* command prompt */
MIXGTK_WIDGET_LOG, /* command output */
MIXGTK_WIDGET_DEV_CONTAINER,
MIXGTK_WIDGET_MIXAL_CONTAINER,
MIXGTK_WIDGET_MIXAL_STATUSBAR,
MIXGTK_WIDGET_rA,
MIXGTK_WIDGET_rX,
MIXGTK_WIDGET_rJ,
MIXGTK_WIDGET_rI1,
MIXGTK_WIDGET_rI2,
MIXGTK_WIDGET_rI3,
MIXGTK_WIDGET_rI4,
MIXGTK_WIDGET_rI5,
MIXGTK_WIDGET_rI6,
MIXGTK_WIDGET_CMP_L,
MIXGTK_WIDGET_CMP_E,
MIXGTK_WIDGET_CMP_G,
MIXGTK_WIDGET_OVER,
MIXGTK_WIDGET_CELLS,
MIXGTK_WIDGET_LAPTIME,
MIXGTK_WIDGET_PROGTIME,
MIXGTK_WIDGET_UPTIME,
MIXGTK_WIDGET_DEVICES,
MIXGTK_WIDGET_LOC,
MIXGTK_WIDGET_GOTO_ENTRY,
MIXGTK_WIDGET_NONE
} mixgtk_widget_id_t;
/* create a new factory from an xml glade file */
extern gboolean
mixgtk_widget_factory_init (void);
/* get a dialog */
extern GtkWidget *
mixgtk_widget_factory_get_dialog (mixgtk_dialog_id_t dlg);
/* get a widget */
extern GtkWidget *
mixgtk_widget_factory_get (mixgtk_dialog_id_t dlg, mixgtk_widget_id_t widget);
/* Get a widget by name */
extern GtkWidget *
mixgtk_widget_factory_get_by_name (const gchar *name);
#endif /* MIXGTK_WIDGETS_H */
mdk-1.3.1/mixgtk/mixgtk_mixvm.h 0000644 0001750 0001750 00000003501 12112755472 012154 /* -*-c-*- ---------------- mixgtk_mixvm.h :
* Functions dealing with the mixvm widgets
* ------------------------------------------------------------------
* Copyright (C) 2001, 2004, 2006, 2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef MIXGTK_MIXVM_H
#define MIXGTK_MIXVM_H
#include
#include "mixgtk.h"
#include "mixgtk_widgets.h"
/* initialise the mixvm widgets */
extern gboolean
mixgtk_mixvm_init (mix_vm_t *vm);
extern void
mixgtk_mixvm_update_fonts (void);
/* update register widgets */
extern void
mixgtk_mixvm_update_registers (void);
/* update the overflow toggle */
extern void
mixgtk_mixvm_update_over_toggle (void);
/* update the comparison flag */
extern void
mixgtk_mixvm_update_cmp (void);
/* update the memory cells */
extern void
mixgtk_mixvm_update_cells (void);
extern void
mixgtk_mixvm_update_cells_to_address (gint address);
/* update the loc pointer */
extern void
mixgtk_mixvm_update_loc (void);
/* update times */
extern void
mixgtk_mixvm_update_times (void);
/* update all mixvm widgets */
extern void
mixgtk_mixvm_update_vm_widgets (void);
#endif /* MIXGTK_MIXVM_H */
mdk-1.3.1/mixgtk/mixgtk_external.h 0000644 0001750 0001750 00000002302 12112755472 012634 /* -*-c-*- -------------- mixgtk_external.h :
* Managing the external programs dialog.
* ------------------------------------------------------------------
* Copyright (C) 2006, 2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef MIXGTK_EXTERNAL_H_0608072329
#define MIXGTK_EXTERNAL_H_0608072329
#include
extern void
mixgtk_external_init (mix_vm_cmd_dispatcher_t *dispatcher);
extern void
on_external_programs_activate ();
#endif // MIXGTK_EXTERNAL_H_0608072329
mdk-1.3.1/mixgtk/Makefile.am 0000644 0001750 0001750 00000003674 12622454575 011335 ## Process this file with automake to produce Makefile.in
# Copyright (C) 2001, 2004, 2006, 2008, 2014 Free Software Foundation, Inc.
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
EXTRA_DIST = mixgtk.glade
if MAKE_GUILE
GUILED = -DMAKE_GUILE
GUILEL = $(top_builddir)/mixguile/libmixguile.a
else
GUILED =
GUILEL =
endif
if DARWIN_SYSTEM
EDITOR_CMD = "/usr/bin/open -a TextEdit %s"
EXTRA_EXECD = -DEXTRA_EXEC_MIME_TYPE
else
EDITOR_CMD = "/usr/bin/xterm -e vi %s"
EXTRA_EXECD =
endif
if MAKE_GUI
pkgdata_DATA = mixgtk.glade
AM_CFLAGS += -I$(includedir) -I$(top_srcdir) \
-DGLADE_FILE=\""$(pkgdatadir)/mixgtk.glade"\"\
-DLOCAL_GLADE_FILE=\""$(srcdir)/mixgtk.glade"\"\
-DDEFAULT_EDITOR_CMD=\"$(EDITOR_CMD)\"\
-DDEFAULT_ASM_CMD="\"$(bindir)/mixasm %s"\"\
$(GUILED) $(EXTRA_EXECD)
LDADD = $(top_builddir)/mixlib/libmix.a $(top_builddir)/lib/libreplace.a\
$(GUILEL) $(INTLLIBS)
if ! DARWIN_SYSTEM
AM_LDFLAGS = -Wl,--export-dynamic
endif
bin_PROGRAMS = gmixvm
gmixvm_SOURCES = gmixvm.c mixgtk.h mixgtk.c \
mixgtk_config.h mixgtk_config.c \
mixgtk_gen_handlers.h mixgtk_gen_handlers.c \
mixgtk_external.h mixgtk_external.c \
mixgtk_cmd_dispatcher.h mixgtk_cmd_dispatcher.c \
mixgtk_widgets.h mixgtk_widgets.c \
mixgtk_device.h mixgtk_device.c \
mixgtk_mixvm.h mixgtk_mixvm.c \
mixgtk_mixal.h mixgtk_mixal.c \
mixgtk_input.h mixgtk_input.c \
mixgtk_fontsel.h mixgtk_fontsel.c \
mixgtk_wm.h mixgtk_wm.c
endif
mdk-1.3.1/mixgtk/mixgtk.glade 0000644 0001750 0001750 00000477407 13743423061 011602
FalseDevices directoryFalseTruecenterdialogTrueFalseverticalTrueFalseendgtk-cancelTrueTrueTrueFalseTrueTrueFalse0gtk-okTrueTrueTrueFalseTrueTrueFalse1FalseFalseend0TrueFalse2511TrueFalseDirectorycenterFalseFalse0TrueFalseFalseFalseFalseFalseFalseTrueTrue1_SelectTrueTrueFalseTrueFalseFalse2FalseTrue2devdir_canceldevdir_okFalseDevice output formatFalseTruecenter-on-parent320dialogTrueFalseverticalTrueFalseendgtk-cancelTrueTrueTrueFalseTrueTrueFalse0gtk-applyTrueTrueTrueFalseTrueTrueFalse1gtk-okTrueTrueTrueFalseTrueTrueFalse2FalseFalseend0TrueFalseS_et all00TrueTrueFalseTrue2413400TrueFalseDevicecenter241000TrueFalseFormatcenter2438Word00TrueTrueFalseTrueTrue8934Decimal00TrueTrueFalseTrueTruewordradio15434100TrueFalse0Truetape0tape1tape2tape3tape4tape5tape6tape7disk0disk1disk2disk3disk4disk5disk6disk7Falsetape0943FalseFalse51button37button38button39FalseDevices550250TrueFalseverticalTrueFalseTrue2iconsTrueFalseTrueDirectoryTruegtk-homeFalseTrueTrueFalseTrueOutputTruegtk-zoom-100FalseTrueTrueFalseFalseFalseTrueFalseTrueFontTruegtk-select-fontFalseTrueTrueFalseFalseFalseTrueFalseTrueAttachTruegtk-dnd-multipleFalseTrueFalseTrue0TrueFalseverticalTrueTrue1False1External programsFalseTruecenter-on-parentdialogTrueFalseverticalTrueFalseendgtk-cancelTrueTrueTrueFalseTrueTrueFalse0gtk-okTrueTrueTrueFalseTrueTrueFalse1FalseFalseend0TrueFalseverticalTrueTrueFalse900TrueTrue-e vi %s1682400TrueFalseEditor command and arguments (e.g -e vi %s)815131TrueFalseFalseFalse824TrueTrue0TrueFalse900TrueFalseMIX asssembler pathTrue0.479999989271163940.529999971389770518815131TrueFalseFalseFalseFalseSelect mixasm executable832Generate listing file15224TrueTrueFalseFalseTrueTrue17632TrueTrue1FalseTrue2button40button41Falsedialogen-gbFalsevertical2FalseendFalseFalse0FalseMemory cellFalseTruedialogFalsevertical2Falseendgtk-cancelTrueTrueFalseTrueTrueTrue0gtk-okTrueTrueTrueTrueFalseTrueTrueTrue1FalseFalse0TrueFalsevertical5TrueFalseGo to addressFalseTrue0TrueTrueTrue4True660.5FalsedigitsFalseFalse1FalseFalse1goto_cancelgoto_okFalseMIX Console inputFalseTruecenter-on-parentdialogTrueFalseverticalTrueFalseendgtk-okTrueTrueTrueTrueFalseTrueTrueFalse0FalseFalseend0TrueFalse3verticalTrueTrueFalseEnter up to 70 charactersFalseFalse0TrueTrue70True70FalseFalse1FalseFalse2okbutton1Falsegmixvmgmixvm-main650550TrueFalse2vertical2TrueFalseTrueFalse_FileTrueFalse_LoadTrueFalseTrueFalsegtk-editTrueFalseTrueTrue_CompileTrueFalseTrueFalseTrueFalsegtk-quitTrueFalseTrueTrueTrueFalseDe_bugTrueFalse_RunTrueFalseTrueFalse_NextTrueFalseTrueFalse_Clear breakpointsTrueFalseTrueFalse_SymbolsTrueFalseTrueFalseTrueFalseVie_wTrueFalse_ToolbarsTrueFalseTrueFalseFalseTrueFalse_Show ToolbarsTrueTrueFalse_StyleTrueFalseTrueFalse_IconsTrueTrueTrueFalse_LabelsTrueTruetb_style_iconsTrueFalse_BothTrueTruetb_style_iconsTrueFalse_SidewaysTrueTruetb_style_icons_Detached windowsTrueFalseTrueFalseFalseTrueFalse_Virtual machineTrueTrueFalse_SourceTrueTrueFalse_DevicesTrueTrueFalseS_ettingsTrueFalseChange _fontTrueFalseTrueFalseFalseTrueFalse_Virtual machineTrueTrueFalse_SourceTrueTrueFalseCommand _promptTrueTrueFalseCommand l_ogTrueTrueFalse_DevicesTrueTrueFalseSymbol _listTrueTrueFalseTrueFalse_AllTrue_Device outputTrueFalseTrueFalseDe_vices dirTrueFalseTrueFalseE_xternal programsTrueFalseTrueFalseTrueFalse_SaveTrueFalseTrueFalseTrueFalseSave on _exitTrueTrueFalse_HelpTrueFalse_AboutTrueFalseTrueFalseFalseTrue0TrueFalseiconsTrueFalseTrueOpenTruegtk-openFalseTrueTrueFalseTrueCompileTruegtk-executeFalseTrueTrueFalseTrueEditTruegtk-justify-fillFalseTrueTrueFalseFalseFalseTrueFalseTrueRunTruegtk-go-forwardFalseTrueTrueFalseTrueNextTruegtk-goto-lastFalseTrueTrueFalseTrueClearTruegtk-clearFalseTrueTrueFalseTrueSymbolsTruegtk-indexFalseTrueTrueFalseFalseFalseTrueFalseDevdirTruegtk-homeFalseTrueTrueFalseFormatTruegtk-zoom-100FalseTrueTrueFalseProgramsTruegtk-preferencesFalseTrueTrueFalseFalseFalseTrueFalseDetachTruegtk-dnd-multipleFalseTrueTrueFalseTrueAttachTruegtk-revert-to-savedFalseTrueFalseTrue1TrueTruevertical1TrueTrueTrueTrueTrueFalseTrueFalseverticalTrueFalsein10TrueFalseFalseword34TrueTrueTrue0TrueTrueTrueFalseFalse1TrueTrueTrueTrue2TrueFalseFalseendbottomFalseFalse3FalseMIXAL source570225TrueFalseverticalTrueFalseTrue2iconsTrueFalseTrueRunTruegtk-go-forwardFalseTrueTrueFalseTrueStepTruegtk-goto-lastFalseTrueTrueFalseTrueClearTruegtk-clearFalseTrueTrueFalseTrueSymbolsTruegtk-indexFalseTrueTrueFalseFalseFalseTrueFalseTrueFontTruegtk-select-fontFalseTrueTrueFalseFalseFalseTrueFalseTrueAttachTruegtk-dnd-multipleFalseTrueFalseTrue0TrueFalseverticalTrueTrue1TrueFalseFalseFalse2FalseVirtual machine640268TrueFalseverticalTrueFalseTrueiconsTrueFalseTrueFontTruegtk-select-fontFalseTrueTrueFalseFalseFalseattach_buttonTrueFalseTrueAttachTruegtk-dnd-multipleFalseTruemenu-barFalseTrue0TrueFalse50TrueFalseTrueFalse1vertical1TrueFalse20TrueFalse83611600TrueFalseAcenterGTK_FILL00TrueFalseI1center23GTK_FILL00TrueFalseI2center2312GTK_FILL00TrueFalseTrueTrueFalse191200TrueTrueFalse9341200TrueTrueFalse93400TrueFalseXcenter12GTK_FILL1616TrueFalseI3center2323GTK_FILL00TrueFalseI4center45GTK_FILL1616TrueFalseI5center4512GTK_FILL1616TrueFalseI6center4523GTK_FILL00TrueFalseJcenter23GTK_FILL00TrueTrueFalse19121200TrueTrueFalse95600TrueTrueFalse9561200TrueTrueFalse9562300TrueTrueFalse93423TrueFalse00TrueTrueFalse9FalseFalse01223GTK_FILLGTK_FILLFalseTrue50TrueFalseTrueFalse20TrueFalse15G00TrueTrueFalse2TrueTrueFalseFalse0E00TrueTrueFalse2TrueTruegreater_radioFalseFalse1L00TrueTrueFalse2TrueTruegreater_radioFalseFalse27TrueFalseFalseFalse3OverflowTrueTrueFalseTrueTrueFalseFalse4FalseFalse0TrueFalse20TrueFalse4100TrueTrueFalse460FalseFalse50TrueTrueFalseTrueFalsegtk-jump-toFalseFalse11FalseFalseend2FalseTrue51TrueFalse20TrueFalse55True00TrueFalseUptime:FalseFalse000TrueFalse500000000centerFalseFalse100TrueFalseElapsed:FalseFalse3200TrueFalse5000000centerFalseFalse300TrueFalseProgram:FalseFalse2400TrueFalse5000000centerFalseFalse5FalseTrue52FalseFalse20TrueFalse70TrueTrue5inTrueTrueGDK_BUTTON_PRESS_MASKTrueTrueTrue3end1TrueTrue1FalseSymbol table245265dictionarydialogTrueFalseverticalTrueFalseendTrueTrueFalseTrueFalse00TrueFalse2TrueFalsegtk-closeFalseFalse0TrueFalse_CloseTrueFalseFalse1TrueFalse0FalseFalseend0TrueFalseinTrueTrueFalseTrueTrueFalseTrue2FalseEnter valueFalseTruemousedialogTrueFalsevertical2TrueFalseendgtk-cancelTrueTrueTrueFalseTrueTrueFalse0gtk-clearTrueTrueFalseTrueFalseTrueTrueFalse1gtk-okTrueTrueTrueFalseTrueTrueFalse2FalseFalseend0TrueFalse500TrueTrueTrueGDK_KEY_PRESS_MASK280886400TrueTrueGDK_KEY_PRESS_MASK2301443200TrueTrueGDK_BUTTON_PRESS_MASK2301763200TrueTrueGDK_KEY_PRESS_MASK2302083200TrueTrueGDK_KEY_PRESS_MASK2302383200TrueTrueGDK_KEY_PRESS_MASK2301123200TrueTrueGDK_KEY_PRESS_MASK12+883200TrueFalseDecimalcenter146800TrueFalseBytescenter153600TrueFalseEnter valuecenter1128FalseTrue2word_cancelword_ok
mdk-1.3.1/mixgtk/mixgtk.c 0000644 0001750 0001750 00000003635 12112755472 010737 /* -*-c-*- -------------- mixgtk.c :
* Main functions of the mix gtk front-end
* ------------------------------------------------------------------
* Copyright (C) 2001, 2002, 2004, 2006, 2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include
#include
#include "mixgtk_widgets.h"
#include "mixgtk_cmd_dispatcher.h"
#include "mixgtk_input.h"
#include "mixgtk_config.h"
#include "mixgtk_wm.h"
#include "mixgtk.h"
/* initialise the app */
gboolean
mixgtk_init (int argc, char *argv[])
{
mix_init_lib ();
gtk_init (&argc, &argv);
if (!mixgtk_config_load ())
{
g_error (_("Unable to load gmixvm configuration"));
}
if (!mixgtk_widget_factory_init ())
{
g_error (_("Unable to initialise application: missing glade file"));
return FALSE;
}
if (!mixgtk_wm_init ())
{
g_error (_("Unable to initialise application\n"));
return FALSE;
}
mixgtk_input_init ();
return TRUE;
}
/* main loop */
void
mixgtk_main (void)
{
gtk_main ();
}
/* clean up */
void
mixgtk_release (void)
{
if (mixgtk_config_is_autosave ()) mixgtk_config_save ();
mix_vm_cmd_dispatcher_delete (mixgtk_cmd_dispatcher_get_mix_dispatcher ());
mix_release_lib ();
}
mdk-1.3.1/mixgtk/mixgtk_gen_handlers.h 0000644 0001750 0001750 00000003123 12112755472 013445 /* -*-c-*- ---------------- mixgtk_gen_handlers.h :
* general signal handlers declarations
* ------------------------------------------------------------------
* Copyright (C) 2001, 2004, 2006, 2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef MIXGTK_GEN_HANDLERS_H
#define MIXGTK_GEN_HANDLERS_H
#include
extern void
on_main_window_destroy (GtkWidget *w, gpointer data);
extern void
on_file_open_activate (GtkWidget *w, gpointer data);
extern void
on_file_exit_activate (GtkWidget *w, gpointer data);
extern void
on_file_edit_activate (GtkWidget *w, gpointer data);
extern void
on_file_compile_activate (GtkWidget *w, gpointer data);
extern void
on_clear_breakpoints_activate (GtkWidget *w, gpointer data);
extern void
on_save_on_exit_toggle (GtkWidget *w, gpointer data);
extern void
on_save_activate (GtkWidget *w, gpointer data);
#endif /* MIXGTK_GEN_HANDLERS_H */
mdk-1.3.1/mixgtk/gmixvm.c 0000644 0001750 0001750 00000005574 12112755472 010747 /* -*-c-*- -------------- gmixvm.c :
* Main function of the mix gtk front-end
* ------------------------------------------------------------------
* Copyright (C) 2001, 2002, 2006, 2007, 2009 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include
#include
#include "mixgtk.h"
static gboolean initfile_ = TRUE;
#ifdef MAKE_GUILE
# include
# include "mixgtk_cmd_dispatcher.h"
static void
inner_main_ (void *closure, int argc, char *argv[])
{
mixgtk_init (argc, argv);
mixguile_set_cmd_dispatcher (mixgtk_cmd_dispatcher_get_mix_dispatcher ());
mixguile_load_bootstrap (initfile_);
mixgtk_main ();
mixgtk_release ();
}
#endif
#ifdef HAVE_GETOPT_LONG
# include
#else
# include
#endif /* HAVE_GETOPT_LONG */
enum {
VER_OPT = 'v',
NOINIT_OPT = 'q',
HELP_OPT = 'h',
USAGE_OPT = 'u'
};
static const char *options_ = "vqhu";
static struct option long_options_[] =
{
{"version", no_argument, 0, VER_OPT},
{"help", no_argument, 0, HELP_OPT},
{"usage", no_argument, 0, USAGE_OPT},
{"noinit", no_argument, 0, NOINIT_OPT},
{0, 0, 0, 0}
};
static void print_usage_ (const gchar *prog)
{
static const char *usage_ =
"Usage: %s [-vhuq] [--version] [--help] [--usage] [--noinit]\n";
fprintf (stderr, usage_, prog);
}
int
main(int argc, char *argv[])
{
int c;
const char *prog_name = argv[0];
setlocale (LC_ALL, "");
bindtextdomain (PACKAGE, LOCALEDIR);
textdomain (PACKAGE);
while (1)
{
c = getopt_long (argc, argv, options_, long_options_, (int*)0);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c)
{
case VER_OPT:
mix_print_license (_("gmixvm, GTK MIX virtual machine"));
return EXIT_SUCCESS;
case NOINIT_OPT:
initfile_ = FALSE;
break;
case HELP_OPT:
case USAGE_OPT:
print_usage_ (prog_name);
return EXIT_SUCCESS;
case '?':
print_usage_ (prog_name);
return EXIT_FAILURE;
default:
g_assert_not_reached ();
break;
}
}
#ifdef MAKE_GUILE
mixguile_enter (argc, argv, inner_main_);
#else
if (!mixgtk_init (argc, argv)) return EXIT_FAILURE;
mixgtk_main ();
mixgtk_release ();
#endif
return EXIT_SUCCESS;
}
mdk-1.3.1/mixgtk/Makefile.in 0000664 0001750 0001750 00000067512 15065042013 011331 # Makefile.in generated by automake 1.17 from Makefile.am.
# @configure_input@
# Copyright (C) 1994-2024 Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# Copyright (C) 2001, 2004, 2006, 2008, 2014 Free Software Foundation, Inc.
#
# This file is free software; as a special exception the author gives
# unlimited permission to copy and/or distribute it, with or without
# modifications, as long as this notice is preserved.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
VPATH = @srcdir@
am__is_gnu_make = { \
if test -z '$(MAKELEVEL)'; then \
false; \
elif test -n '$(MAKE_HOST)'; then \
true; \
elif test -n '$(MAKE_VERSION)' && test -n '$(CURDIR)'; then \
true; \
else \
false; \
fi; \
}
am__make_running_with_option = \
case $${target_option-} in \
?) ;; \
*) echo "am__make_running_with_option: internal error: invalid" \
"target option '$${target_option-}' specified" >&2; \
exit 1;; \
esac; \
has_opt=no; \
sane_makeflags=$$MAKEFLAGS; \
if $(am__is_gnu_make); then \
sane_makeflags=$$MFLAGS; \
else \
case $$MAKEFLAGS in \
*\\[\ \ ]*) \
bs=\\; \
sane_makeflags=`printf '%s\n' "$$MAKEFLAGS" \
| sed "s/$$bs$$bs[$$bs $$bs ]*//g"`;; \
esac; \
fi; \
skip_next=no; \
strip_trailopt () \
{ \
flg=`printf '%s\n' "$$flg" | sed "s/$$1.*$$//"`; \
}; \
for flg in $$sane_makeflags; do \
test $$skip_next = yes && { skip_next=no; continue; }; \
case $$flg in \
*=*|--*) continue;; \
-*I) strip_trailopt 'I'; skip_next=yes;; \
-*I?*) strip_trailopt 'I';; \
-*O) strip_trailopt 'O'; skip_next=yes;; \
-*O?*) strip_trailopt 'O';; \
-*l) strip_trailopt 'l'; skip_next=yes;; \
-*l?*) strip_trailopt 'l';; \
-[dEDm]) skip_next=yes;; \
-[JT]) skip_next=yes;; \
esac; \
case $$flg in \
*$$target_option*) has_opt=yes; break;; \
esac; \
done; \
test $$has_opt = yes
am__make_dryrun = (target_option=n; $(am__make_running_with_option))
am__make_keepgoing = (target_option=k; $(am__make_running_with_option))
am__rm_f = rm -f $(am__rm_f_notfound)
am__rm_rf = rm -rf $(am__rm_f_notfound)
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
@MAKE_GUI_TRUE@am__append_1 = -I$(includedir) -I$(top_srcdir) \
@MAKE_GUI_TRUE@ -DGLADE_FILE=\""$(pkgdatadir)/mixgtk.glade"\"\
@MAKE_GUI_TRUE@ -DLOCAL_GLADE_FILE=\""$(srcdir)/mixgtk.glade"\"\
@MAKE_GUI_TRUE@ -DDEFAULT_EDITOR_CMD=\"$(EDITOR_CMD)\"\
@MAKE_GUI_TRUE@ -DDEFAULT_ASM_CMD="\"$(bindir)/mixasm %s"\"\
@MAKE_GUI_TRUE@ $(GUILED) $(EXTRA_EXECD)
@MAKE_GUI_TRUE@bin_PROGRAMS = gmixvm$(EXEEXT)
subdir = mixgtk
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/m4/codeset.m4 \
$(top_srcdir)/m4/gettext.m4 $(top_srcdir)/m4/glibc21.m4 \
$(top_srcdir)/m4/iconv.m4 $(top_srcdir)/m4/intdiv0.m4 \
$(top_srcdir)/m4/intmax.m4 $(top_srcdir)/m4/inttypes-pri.m4 \
$(top_srcdir)/m4/inttypes.m4 $(top_srcdir)/m4/inttypes_h.m4 \
$(top_srcdir)/m4/isc-posix.m4 $(top_srcdir)/m4/lcmessage.m4 \
$(top_srcdir)/m4/lib-ld.m4 $(top_srcdir)/m4/lib-link.m4 \
$(top_srcdir)/m4/lib-prefix.m4 $(top_srcdir)/m4/longdouble.m4 \
$(top_srcdir)/m4/longlong.m4 $(top_srcdir)/m4/nls.m4 \
$(top_srcdir)/m4/po.m4 $(top_srcdir)/m4/printf-posix.m4 \
$(top_srcdir)/m4/progtest.m4 $(top_srcdir)/m4/signed.m4 \
$(top_srcdir)/m4/size_max.m4 $(top_srcdir)/m4/stdint_h.m4 \
$(top_srcdir)/m4/uintmax_t.m4 $(top_srcdir)/m4/ulonglong.m4 \
$(top_srcdir)/m4/wchar_t.m4 $(top_srcdir)/m4/wint_t.m4 \
$(top_srcdir)/m4/xsize.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
DIST_COMMON = $(srcdir)/Makefile.am $(am__DIST_COMMON)
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/config.h
CONFIG_CLEAN_FILES =
CONFIG_CLEAN_VPATH_FILES =
am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgdatadir)"
PROGRAMS = $(bin_PROGRAMS)
am__gmixvm_SOURCES_DIST = gmixvm.c mixgtk.h mixgtk.c mixgtk_config.h \
mixgtk_config.c mixgtk_gen_handlers.h mixgtk_gen_handlers.c \
mixgtk_external.h mixgtk_external.c mixgtk_cmd_dispatcher.h \
mixgtk_cmd_dispatcher.c mixgtk_widgets.h mixgtk_widgets.c \
mixgtk_device.h mixgtk_device.c mixgtk_mixvm.h mixgtk_mixvm.c \
mixgtk_mixal.h mixgtk_mixal.c mixgtk_input.h mixgtk_input.c \
mixgtk_fontsel.h mixgtk_fontsel.c mixgtk_wm.h mixgtk_wm.c
@MAKE_GUI_TRUE@am_gmixvm_OBJECTS = gmixvm.$(OBJEXT) mixgtk.$(OBJEXT) \
@MAKE_GUI_TRUE@ mixgtk_config.$(OBJEXT) \
@MAKE_GUI_TRUE@ mixgtk_gen_handlers.$(OBJEXT) \
@MAKE_GUI_TRUE@ mixgtk_external.$(OBJEXT) \
@MAKE_GUI_TRUE@ mixgtk_cmd_dispatcher.$(OBJEXT) \
@MAKE_GUI_TRUE@ mixgtk_widgets.$(OBJEXT) \
@MAKE_GUI_TRUE@ mixgtk_device.$(OBJEXT) mixgtk_mixvm.$(OBJEXT) \
@MAKE_GUI_TRUE@ mixgtk_mixal.$(OBJEXT) mixgtk_input.$(OBJEXT) \
@MAKE_GUI_TRUE@ mixgtk_fontsel.$(OBJEXT) mixgtk_wm.$(OBJEXT)
gmixvm_OBJECTS = $(am_gmixvm_OBJECTS)
gmixvm_LDADD = $(LDADD)
@MAKE_GUILE_TRUE@am__DEPENDENCIES_1 = \
@MAKE_GUILE_TRUE@ $(top_builddir)/mixguile/libmixguile.a
am__DEPENDENCIES_2 =
@MAKE_GUI_TRUE@gmixvm_DEPENDENCIES = $(top_builddir)/mixlib/libmix.a \
@MAKE_GUI_TRUE@ $(top_builddir)/lib/libreplace.a \
@MAKE_GUI_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_2)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
am__v_P_0 = false
am__v_P_1 = :
AM_V_GEN = $(am__v_GEN_@AM_V@)
am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
am__v_GEN_0 = @echo " GEN " $@;
am__v_GEN_1 =
AM_V_at = $(am__v_at_@AM_V@)
am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
am__v_at_0 = @
am__v_at_1 =
DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__maybe_remake_depfiles = depfiles
am__depfiles_remade = ./$(DEPDIR)/gmixvm.Po ./$(DEPDIR)/mixgtk.Po \
./$(DEPDIR)/mixgtk_cmd_dispatcher.Po \
./$(DEPDIR)/mixgtk_config.Po ./$(DEPDIR)/mixgtk_device.Po \
./$(DEPDIR)/mixgtk_external.Po ./$(DEPDIR)/mixgtk_fontsel.Po \
./$(DEPDIR)/mixgtk_gen_handlers.Po ./$(DEPDIR)/mixgtk_input.Po \
./$(DEPDIR)/mixgtk_mixal.Po ./$(DEPDIR)/mixgtk_mixvm.Po \
./$(DEPDIR)/mixgtk_widgets.Po ./$(DEPDIR)/mixgtk_wm.Po
am__mv = mv -f
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
AM_V_CC = $(am__v_CC_@AM_V@)
am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
am__v_CC_0 = @echo " CC " $@;
am__v_CC_1 =
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
AM_V_CCLD = $(am__v_CCLD_@AM_V@)
am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
am__v_CCLD_0 = @echo " CCLD " $@;
am__v_CCLD_1 =
SOURCES = $(gmixvm_SOURCES)
DIST_SOURCES = $(am__gmixvm_SOURCES_DIST)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
n|no|NO) false;; \
*) (install-info --version) >/dev/null 2>&1;; \
esac
am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
am__vpath_adj = case $$p in \
$(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
*) f=$$p;; \
esac;
am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
am__install_max = 40
am__nobase_strip_setup = \
srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
am__nobase_strip = \
for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
am__nobase_list = $(am__nobase_strip_setup); \
for p in $$list; do echo "$$p $$p"; done | \
sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
$(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
if (++n[$$2] == $(am__install_max)) \
{ print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
END { for (dir in files) print dir, files[dir] }'
am__base_list = \
sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
am__uninstall_files_from_dir = { \
{ test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
|| { echo " ( cd '$$dir' && rm -f" $$files ")"; \
$(am__cd) "$$dir" && echo $$files | $(am__xargs_n) 40 $(am__rm_f); }; \
}
DATA = $(pkgdata_DATA)
am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP)
# Read a list of newline-separated strings from the standard input,
# and print each of them once, without duplicates. Input order is
# *not* preserved.
am__uniquify_input = $(AWK) '\
BEGIN { nonempty = 0; } \
{ items[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in items) print i; }; } \
'
# Make sure the list of sources is unique. This is necessary because,
# e.g., the same source file might be shared among _SOURCES variables
# for different programs/libraries.
am__define_uniq_tagged_files = \
list='$(am__tagged_files)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | $(am__uniquify_input)`
am__DIST_COMMON = $(srcdir)/Makefile.in $(top_srcdir)/depcomp \
$(top_srcdir)/mkinstalldirs
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
ACLOCAL = @ACLOCAL@
ALLOCA = @ALLOCA@
ALL_LINGUAS = @ALL_LINGUAS@
AMTAR = @AMTAR@
AM_CFLAGS = @AM_CFLAGS@ $(am__append_1)
AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@
CATOBJEXT = @CATOBJEXT@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CSCOPE = @CSCOPE@
CTAGS = @CTAGS@
CYGPATH_W = @CYGPATH_W@
DATADIRNAME = @DATADIRNAME@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ETAGS = @ETAGS@
EXEEXT = @EXEEXT@
GENCAT = @GENCAT@
GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
GLIBC21 = @GLIBC21@
GLIB_CFLAGS = @GLIB_CFLAGS@
GLIB_LIBS = @GLIB_LIBS@
GMSGFMT = @GMSGFMT@
GREP = @GREP@
GTK_CFLAGS = @GTK_CFLAGS@
GTK_LIBS = @GTK_LIBS@
GUILE_CFLAGS = @GUILE_CFLAGS@
GUILE_LIBS = @GUILE_LIBS@
HAVE_ASPRINTF = @HAVE_ASPRINTF@
HAVE_POSIX_PRINTF = @HAVE_POSIX_PRINTF@
HAVE_SNPRINTF = @HAVE_SNPRINTF@
HAVE_WPRINTF = @HAVE_WPRINTF@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
INSTOBJEXT = @INSTOBJEXT@
INTLBISON = @INTLBISON@
INTLLIBS = @INTLLIBS@
INTLOBJS = @INTLOBJS@
INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
INTLTOOL_MERGE = @INTLTOOL_MERGE@
INTLTOOL_PERL = @INTLTOOL_PERL@
INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@
LDFLAGS = @LDFLAGS@
LEX = @LEX@
LEXLIB = @LEXLIB@
LEX_OUTPUT_ROOT = @LEX_OUTPUT_ROOT@
LIBICONV = @LIBICONV@
LIBINTL = @LIBINTL@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LTLIBICONV = @LTLIBICONV@
LTLIBINTL = @LTLIBINTL@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MAKE_GUILE = @MAKE_GUILE@
MKDIR_P = @MKDIR_P@
MKINSTALLDIRS = @MKINSTALLDIRS@
MSGFMT = @MSGFMT@
MSGMERGE = @MSGMERGE@
OBJEXT = @OBJEXT@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PKG_CONFIG = @PKG_CONFIG@
PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
POSUB = @POSUB@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@
USE_NLS = @USE_NLS@
VERSION = @VERSION@
XGETTEXT = @XGETTEXT@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
am__rm_f_notfound = @am__rm_f_notfound@
am__tar = @am__tar@
am__untar = @am__untar@
am__xargs_n = @am__xargs_n@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
intltool__v_merge_options_ = @intltool__v_merge_options_@
intltool__v_merge_options_0 = @intltool__v_merge_options_0@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
runstatedir = @runstatedir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
EXTRA_DIST = mixgtk.glade
@MAKE_GUILE_FALSE@GUILED =
@MAKE_GUILE_TRUE@GUILED = -DMAKE_GUILE
@MAKE_GUILE_FALSE@GUILEL =
@MAKE_GUILE_TRUE@GUILEL = $(top_builddir)/mixguile/libmixguile.a
@DARWIN_SYSTEM_FALSE@EDITOR_CMD = "/usr/bin/xterm -e vi %s"
@DARWIN_SYSTEM_TRUE@EDITOR_CMD = "/usr/bin/open -a TextEdit %s"
@DARWIN_SYSTEM_FALSE@EXTRA_EXECD =
@DARWIN_SYSTEM_TRUE@EXTRA_EXECD = -DEXTRA_EXEC_MIME_TYPE
@MAKE_GUI_TRUE@pkgdata_DATA = mixgtk.glade
@MAKE_GUI_TRUE@LDADD = $(top_builddir)/mixlib/libmix.a $(top_builddir)/lib/libreplace.a\
@MAKE_GUI_TRUE@ $(GUILEL) $(INTLLIBS)
@DARWIN_SYSTEM_FALSE@@MAKE_GUI_TRUE@AM_LDFLAGS = -Wl,--export-dynamic
@MAKE_GUI_TRUE@gmixvm_SOURCES = gmixvm.c mixgtk.h mixgtk.c \
@MAKE_GUI_TRUE@ mixgtk_config.h mixgtk_config.c \
@MAKE_GUI_TRUE@ mixgtk_gen_handlers.h mixgtk_gen_handlers.c \
@MAKE_GUI_TRUE@ mixgtk_external.h mixgtk_external.c \
@MAKE_GUI_TRUE@ mixgtk_cmd_dispatcher.h mixgtk_cmd_dispatcher.c \
@MAKE_GUI_TRUE@ mixgtk_widgets.h mixgtk_widgets.c \
@MAKE_GUI_TRUE@ mixgtk_device.h mixgtk_device.c \
@MAKE_GUI_TRUE@ mixgtk_mixvm.h mixgtk_mixvm.c \
@MAKE_GUI_TRUE@ mixgtk_mixal.h mixgtk_mixal.c \
@MAKE_GUI_TRUE@ mixgtk_input.h mixgtk_input.c \
@MAKE_GUI_TRUE@ mixgtk_fontsel.h mixgtk_fontsel.c \
@MAKE_GUI_TRUE@ mixgtk_wm.h mixgtk_wm.c
all: all-am
.SUFFIXES:
.SUFFIXES: .c .o .obj
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
&& { if test -f $@; then exit 0; else break; fi; }; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu mixgtk/Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --gnu mixgtk/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles)'; \
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__maybe_remake_depfiles);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
$(am__aclocal_m4_deps):
install-binPROGRAMS: $(bin_PROGRAMS)
@$(NORMAL_INSTALL)
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(bindir)'"; \
$(MKDIR_P) "$(DESTDIR)$(bindir)" || exit 1; \
fi; \
for p in $$list; do echo "$$p $$p"; done | \
sed 's/$(EXEEXT)$$//' | \
while read p p1; do if test -f $$p \
; then echo "$$p"; echo "$$p"; else :; fi; \
done | \
sed -e 'p;s,.*/,,;n;h' \
-e 's|.*|.|' \
-e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
sed 'N;N;N;s,\n, ,g' | \
$(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
{ d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
if ($$2 == $$4) files[d] = files[d] " " $$1; \
else { print "f", $$3 "/" $$4, $$1; } } \
END { for (d in files) print "f", d, files[d] }' | \
while read type dir files; do \
if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
test -z "$$files" || { \
echo " $(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \
$(INSTALL_PROGRAM_ENV) $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \
} \
; done
uninstall-binPROGRAMS:
@$(NORMAL_UNINSTALL)
@list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \
files=`for p in $$list; do echo "$$p"; done | \
sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
-e 's/$$/$(EXEEXT)/' \
`; \
test -n "$$list" || exit 0; \
echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \
cd "$(DESTDIR)$(bindir)" && $(am__rm_f) $$files
clean-binPROGRAMS:
-$(am__rm_f) $(bin_PROGRAMS)
gmixvm$(EXEEXT): $(gmixvm_OBJECTS) $(gmixvm_DEPENDENCIES) $(EXTRA_gmixvm_DEPENDENCIES)
@rm -f gmixvm$(EXEEXT)
$(AM_V_CCLD)$(LINK) $(gmixvm_OBJECTS) $(gmixvm_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gmixvm.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixgtk.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixgtk_cmd_dispatcher.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixgtk_config.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixgtk_device.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixgtk_external.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixgtk_fontsel.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixgtk_gen_handlers.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixgtk_input.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixgtk_mixal.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixgtk_mixvm.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixgtk_widgets.Po@am__quote@ # am--include-marker
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mixgtk_wm.Po@am__quote@ # am--include-marker
$(am__depfiles_remade):
@$(MKDIR_P) $(@D)
@: >>$@
am--depfiles: $(am__depfiles_remade)
.c.o:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ $<
.c.obj:
@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c -o $@ `$(CYGPATH_W) '$<'`
install-pkgdataDATA: $(pkgdata_DATA)
@$(NORMAL_INSTALL)
@list='$(pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \
if test -n "$$list"; then \
echo " $(MKDIR_P) '$(DESTDIR)$(pkgdatadir)'"; \
$(MKDIR_P) "$(DESTDIR)$(pkgdatadir)" || exit 1; \
fi; \
for p in $$list; do \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
echo "$$d$$p"; \
done | $(am__base_list) | \
while read files; do \
echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(pkgdatadir)'"; \
$(INSTALL_DATA) $$files "$(DESTDIR)$(pkgdatadir)" || exit $$?; \
done
uninstall-pkgdataDATA:
@$(NORMAL_UNINSTALL)
@list='$(pkgdata_DATA)'; test -n "$(pkgdatadir)" || list=; \
files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \
dir='$(DESTDIR)$(pkgdatadir)'; $(am__uninstall_files_from_dir)
ID: $(am__tagged_files)
$(am__define_uniq_tagged_files); mkid -fID $$unique
tags: tags-am
TAGS: tags
tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
set x; \
here=`pwd`; \
$(am__define_uniq_tagged_files); \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: ctags-am
CTAGS: ctags
ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files)
$(am__define_uniq_tagged_files); \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
cscopelist: cscopelist-am
cscopelist-am: $(am__tagged_files)
list='$(am__tagged_files)'; \
case "$(srcdir)" in \
[\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \
*) sdir=$(subdir)/$(srcdir) ;; \
esac; \
for i in $$list; do \
if test -f "$$i"; then \
echo "$(subdir)/$$i"; \
else \
echo "$$sdir/$$i"; \
fi; \
done >> $(top_builddir)/cscope.files
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
distdir: $(BUILT_SOURCES)
$(MAKE) $(AM_MAKEFLAGS) distdir-am
distdir-am: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
list='$(DISTFILES)'; \
dist_files=`for file in $$list; do echo $$file; done | \
sed -e "s|^$$srcdirstrip/||;t" \
-e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
case $$dist_files in \
*/*) $(MKDIR_P) `echo "$$dist_files" | \
sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
sort -u` ;; \
esac; \
for file in $$dist_files; do \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
if test -d $$d/$$file; then \
dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
if test -d "$(distdir)/$$file"; then \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
fi; \
cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
else \
test -f "$(distdir)/$$file" \
|| cp -p $$d/$$file "$(distdir)/$$file" \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(PROGRAMS) $(DATA)
installdirs:
for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkgdatadir)"; do \
test -z "$$dir" || $(MKDIR_P) "$$dir"; \
done
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
if test -z '$(STRIP)'; then \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
install; \
else \
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
"INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
fi
mostlyclean-generic:
clean-generic:
distclean-generic:
-$(am__rm_f) $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || $(am__rm_f) $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-binPROGRAMS clean-generic mostlyclean-am
distclean: distclean-am
-rm -f ./$(DEPDIR)/gmixvm.Po
-rm -f ./$(DEPDIR)/mixgtk.Po
-rm -f ./$(DEPDIR)/mixgtk_cmd_dispatcher.Po
-rm -f ./$(DEPDIR)/mixgtk_config.Po
-rm -f ./$(DEPDIR)/mixgtk_device.Po
-rm -f ./$(DEPDIR)/mixgtk_external.Po
-rm -f ./$(DEPDIR)/mixgtk_fontsel.Po
-rm -f ./$(DEPDIR)/mixgtk_gen_handlers.Po
-rm -f ./$(DEPDIR)/mixgtk_input.Po
-rm -f ./$(DEPDIR)/mixgtk_mixal.Po
-rm -f ./$(DEPDIR)/mixgtk_mixvm.Po
-rm -f ./$(DEPDIR)/mixgtk_widgets.Po
-rm -f ./$(DEPDIR)/mixgtk_wm.Po
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am: install-pkgdataDATA
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-binPROGRAMS
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -f ./$(DEPDIR)/gmixvm.Po
-rm -f ./$(DEPDIR)/mixgtk.Po
-rm -f ./$(DEPDIR)/mixgtk_cmd_dispatcher.Po
-rm -f ./$(DEPDIR)/mixgtk_config.Po
-rm -f ./$(DEPDIR)/mixgtk_device.Po
-rm -f ./$(DEPDIR)/mixgtk_external.Po
-rm -f ./$(DEPDIR)/mixgtk_fontsel.Po
-rm -f ./$(DEPDIR)/mixgtk_gen_handlers.Po
-rm -f ./$(DEPDIR)/mixgtk_input.Po
-rm -f ./$(DEPDIR)/mixgtk_mixal.Po
-rm -f ./$(DEPDIR)/mixgtk_mixvm.Po
-rm -f ./$(DEPDIR)/mixgtk_widgets.Po
-rm -f ./$(DEPDIR)/mixgtk_wm.Po
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-binPROGRAMS uninstall-pkgdataDATA
.MAKE: install-am install-strip
.PHONY: CTAGS GTAGS TAGS all all-am am--depfiles check check-am clean \
clean-binPROGRAMS clean-generic cscopelist-am ctags ctags-am \
distclean distclean-compile distclean-generic distclean-tags \
distdir dvi dvi-am html html-am info info-am install \
install-am install-binPROGRAMS install-data install-data-am \
install-dvi install-dvi-am install-exec install-exec-am \
install-html install-html-am install-info install-info-am \
install-man install-pdf install-pdf-am install-pkgdataDATA \
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
mostlyclean-generic pdf pdf-am ps ps-am tags tags-am uninstall \
uninstall-am uninstall-binPROGRAMS uninstall-pkgdataDATA
.PRECIOUS: Makefile
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
# Tell GNU make to disable its built-in pattern rules.
%:: %,v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%
mdk-1.3.1/depcomp 0000755 0001750 0001750 00000056217 14767572401 007355 #! /bin/sh
# depcomp - compile a program generating dependencies as side-effects
scriptversion=2024-06-19.01; # UTC
# Copyright (C) 1999-2024 Free Software Foundation, Inc.
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
# As a special exception to the GNU General Public License, if you
# distribute this file as part of a program that contains a
# configuration script generated by Autoconf, you may include it under
# the same distribution terms that you use for the rest of that program.
# Originally written by Alexandre Oliva .
case $1 in
'')
echo "$0: No command. Try '$0 --help' for more information." 1>&2
exit 1;
;;
-h | --h*)
cat <<\EOF
Usage: depcomp [--help] [--version] PROGRAM [ARGS]
Run PROGRAMS ARGS to compile a file, generating dependencies
as side-effects.
Environment variables:
depmode Dependency tracking mode.
source Source file read by 'PROGRAMS ARGS'.
object Object file output by 'PROGRAMS ARGS'.
DEPDIR directory where to store dependencies.
depfile Dependency file to output.
tmpdepfile Temporary file to use when outputting dependencies.
libtool Whether libtool is used (yes/no).
Report bugs to .
GNU Automake home page: .
General help using GNU software: .
EOF
exit $?
;;
-v | --v*)
echo "depcomp (GNU Automake) $scriptversion"
exit $?
;;
esac
# Get the directory component of the given path, and save it in the
# global variables '$dir'. Note that this directory component will
# be either empty or ending with a '/' character. This is deliberate.
set_dir_from ()
{
case $1 in
*/*) dir=`echo "$1" | sed -e 's|/[^/]*$|/|'`;;
*) dir=;;
esac
}
# Get the suffix-stripped basename of the given path, and save it the
# global variable '$base'.
set_base_from ()
{
base=`echo "$1" | sed -e 's|^.*/||' -e 's/\.[^.]*$//'`
}
# If no dependency file was actually created by the compiler invocation,
# we still have to create a dummy depfile, to avoid errors with the
# Makefile "include basename.Plo" scheme.
make_dummy_depfile ()
{
echo "#dummy" > "$depfile"
}
# Factor out some common post-processing of the generated depfile.
# Requires the auxiliary global variable '$tmpdepfile' to be set.
aix_post_process_depfile ()
{
# If the compiler actually managed to produce a dependency file,
# post-process it.
if test -f "$tmpdepfile"; then
# Each line is of the form 'foo.o: dependency.h'.
# Do two passes, one to just change these to
# $object: dependency.h
# and one to simply output
# dependency.h:
# which is needed to avoid the deleted-header problem.
{ sed -e "s,^.*\.[$lower]*:,$object:," < "$tmpdepfile"
sed -e "s,^.*\.[$lower]*:[$tab ]*,," -e 's,$,:,' < "$tmpdepfile"
} > "$depfile"
rm -f "$tmpdepfile"
else
make_dummy_depfile
fi
}
# A tabulation character.
tab=' '
# A newline character.
nl='
'
# Character ranges might be problematic outside the C locale.
# These definitions help.
upper=ABCDEFGHIJKLMNOPQRSTUVWXYZ
lower=abcdefghijklmnopqrstuvwxyz
alpha=${upper}${lower}
if test -z "$depmode" || test -z "$source" || test -z "$object"; then
echo "depcomp: Variables source, object and depmode must be set" 1>&2
exit 1
fi
# Dependencies for sub/bar.o or sub/bar.obj go into sub/.deps/bar.Po.
depfile=${depfile-`echo "$object" |
sed 's|[^\\/]*$|'${DEPDIR-.deps}'/&|;s|\.\([^.]*\)$|.P\1|;s|Pobj$|Po|'`}
tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`}
rm -f "$tmpdepfile"
# Avoid interference from the environment.
gccflag= dashmflag=
# Some modes work just like other modes, but use different flags. We
# parameterize here, but still list the modes in the big case below,
# to make depend.m4 easier to write. Note that we *cannot* use a case
# here, because this file can only contain one case statement.
if test "$depmode" = hp; then
# HP compiler uses -M and no extra arg.
gccflag=-M
depmode=gcc
fi
if test "$depmode" = dashXmstdout; then
# This is just like dashmstdout with a different argument.
dashmflag=-xM
depmode=dashmstdout
fi
cygpath_u="cygpath -u -f -"
if test "$depmode" = msvcmsys; then
# This is just like msvisualcpp but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvisualcpp
fi
if test "$depmode" = msvc7msys; then
# This is just like msvc7 but w/o cygpath translation.
# Just convert the backslash-escaped backslashes to single forward
# slashes to satisfy depend.m4
cygpath_u='sed s,\\\\,/,g'
depmode=msvc7
fi
if test "$depmode" = xlc; then
# IBM C/C++ Compilers xlc/xlC can output gcc-like dependency information.
gccflag=-qmakedep=gcc,-MF
depmode=gcc
fi
case "$depmode" in
gcc3)
## gcc 3 implements dependency tracking that does exactly what
## we want. Yay! Note: for some reason libtool 1.4 doesn't like
## it if -MD -MP comes after the -MF stuff. Hmm.
## Unfortunately, FreeBSD c89 acceptance of flags depends upon
## the command line argument order; so add the flags where they
## appear in depend2.am. Note that the slowdown incurred here
## affects only configure: in makefiles, %FASTDEP% shortcuts this.
for arg
do
case $arg in
-c) set fnord "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" "$arg" ;;
*) set fnord "$@" "$arg" ;;
esac
shift # fnord
shift # $arg
done
"$@"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
mv "$tmpdepfile" "$depfile"
;;
gcc)
## Note that this doesn't just cater to obsolete pre-3.x GCC compilers.
## but also to in-use compilers like IBM xlc/xlC and the HP C compiler.
## (see the conditional assignment to $gccflag above).
## There are various ways to get dependency output from gcc. Here's
## why we pick this rather obscure method:
## - Don't want to use -MD because we'd like the dependencies to end
## up in a subdir. Having to rename by hand is ugly.
## (We might end up doing this anyway to support other compilers.)
## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like
## -MM, not -M (despite what the docs say). Also, it might not be
## supported by the other compilers which use the 'gcc' depmode.
## - Using -M directly means running the compiler twice (even worse
## than renaming).
if test -z "$gccflag"; then
gccflag=-MD,
fi
"$@" -Wp,"$gccflag$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The second -e expression handles DOS-style file names with drive
# letters.
sed -e 's/^[^:]*: / /' \
-e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile"
## This next piece of magic avoids the "deleted header file" problem.
## The problem is that when a header file which appears in a .P file
## is deleted, the dependency causes make to die (because there is
## typically no way to rebuild the header). We avoid this by adding
## dummy dependencies for each header file. Too bad gcc doesn't do
## this for us directly.
## Some versions of gcc put a space before the ':'. On the theory
## that the space means something, we add a space to the output as
## well. hp depmode also adds that space, but also prefixes the VPATH
## to the object. Take care to not repeat it in the output.
## Some versions of the HPUX 10.20 sed can't process this invocation
## correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e "s|.*$object$||" -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
sgi)
if test "$libtool" = yes; then
"$@" "-Wp,-MDupdate,$tmpdepfile"
else
"$@" -MDupdate "$tmpdepfile"
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files
echo "$object : \\" > "$depfile"
# Clip off the initial element (the dependent). Don't try to be
# clever and replace this with sed code, as IRIX sed won't handle
# lines with more than a fixed number of characters (4096 in
# IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines;
# the IRIX cc adds comments like '#:fec' to the end of the
# dependency line.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' \
| tr "$nl" ' ' >> "$depfile"
echo >> "$depfile"
# The second pass generates a dummy entry for each header file.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \
>> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile"
;;
xlc)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
aix)
# The C for AIX Compiler uses -M and outputs the dependencies
# in a .u file. In older versions, this file always lives in the
# current directory. Also, the AIX compiler puts '$object:' at the
# start of each line; $object doesn't have directory information.
# Version 6 uses the directory in both cases.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.u
tmpdepfile2=$base.u
tmpdepfile3=$dir.libs/$base.u
"$@" -Wc,-M
else
tmpdepfile1=$dir$base.u
tmpdepfile2=$dir$base.u
tmpdepfile3=$dir$base.u
"$@" -M
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
aix_post_process_depfile
;;
tcc)
# tcc (Tiny C Compiler) understand '-MD -MF file' since version 0.9.26
# FIXME: That version still under development at the moment of writing.
# Make that this statement remains true also for stable, released
# versions.
# It will wrap lines (doesn't matter whether long or short) with a
# trailing '\', as in:
#
# foo.o : \
# foo.c \
# foo.h \
#
# It will put a trailing '\' even on the last line, and will use leading
# spaces rather than leading tabs (at least since its commit 0394caf7
# "Emit spaces for -MD").
"$@" -MD -MF "$tmpdepfile"
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each non-empty line is of the form 'foo.o : \' or ' dep.h \'.
# We have to change lines of the first kind to '$object: \'.
sed -e "s|.*:|$object :|" < "$tmpdepfile" > "$depfile"
# And for each line of the second kind, we have to emit a 'dep.h:'
# dummy dependency, to avoid the deleted-header problem.
sed -n -e 's|^ *\(.*\) *\\$|\1:|p' < "$tmpdepfile" >> "$depfile"
rm -f "$tmpdepfile"
;;
## The order of this option in the case statement is important, since the
## shell code in configure will try each of these formats in the order
## listed in this file. A plain '-MD' option would be understood by many
## compilers, so we must ensure this comes after the gcc and icc options.
pgcc)
# Portland's C compiler understands '-MD'.
# Will always output deps to 'file.d' where file is the root name of the
# source file under compilation, even if file resides in a subdirectory.
# The object file name does not affect the name of the '.d' file.
# pgcc 10.2 will output
# foo.o: sub/foo.c sub/foo.h
# and will wrap long lines using '\' :
# foo.o: sub/foo.c ... \
# sub/foo.h ... \
# ...
set_dir_from "$object"
# Use the source, not the object, to determine the base name, since
# that's sadly what pgcc will do too.
set_base_from "$source"
tmpdepfile=$base.d
# For projects that build the same source file twice into different object
# files, the pgcc approach of using the *source* file root name can cause
# problems in parallel builds. Use a locking strategy to avoid stomping on
# the same $tmpdepfile.
lockdir=$base.d-lock
trap "
echo '$0: caught signal, cleaning up...' >&2
rmdir '$lockdir'
exit 1
" 1 2 13 15
numtries=100
i=$numtries
while test $i -gt 0; do
# mkdir is a portable test-and-set.
if mkdir "$lockdir" 2>/dev/null; then
# This process acquired the lock.
"$@" -MD
stat=$?
# Release the lock.
rmdir "$lockdir"
break
else
# If the lock is being held by a different process, wait
# until the winning process is done or we timeout.
while test -d "$lockdir" && test $i -gt 0; do
sleep 1
i=`expr $i - 1`
done
fi
i=`expr $i - 1`
done
trap - 1 2 13 15
if test $i -le 0; then
echo "$0: failed to acquire lock after $numtries attempts" >&2
echo "$0: check lockdir '$lockdir'" >&2
exit 1
fi
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
# Each line is of the form `foo.o: dependent.h',
# or `foo.o: dep1.h dep2.h \', or ` dep3.h dep4.h \'.
# Do two passes, one to just change these to
# `$object: dependent.h' and one to simply `dependent.h:'.
sed "s,^[^:]*:,$object :," < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed 's,^[^:]*: \(.*\)$,\1,;s/^\\$//;/^$/d;/:$/d' < "$tmpdepfile" \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
hp2)
# The "hp" stanza above does not work with aCC (C++) and HP's ia64
# compilers, which have integrated preprocessors. The correct option
# to use with these is +Maked; it writes dependencies to a file named
# 'foo.d', which lands next to the object file, wherever that
# happens to be.
# Much of this is similar to the tru64 case; see comments there.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir.libs/$base.d
"$@" -Wc,+Maked
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
"$@" +Maked
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2"
do
test -f "$tmpdepfile" && break
done
if test -f "$tmpdepfile"; then
sed -e "s,^.*\.[$lower]*:,$object:," "$tmpdepfile" > "$depfile"
# Add 'dependent.h:' lines.
sed -ne '2,${
s/^ *//
s/ \\*$//
s/$/:/
p
}' "$tmpdepfile" >> "$depfile"
else
make_dummy_depfile
fi
rm -f "$tmpdepfile" "$tmpdepfile2"
;;
tru64)
# The Tru64 compiler uses -MD to generate dependencies as a side
# effect. 'cc -MD -o foo.o ...' puts the dependencies into 'foo.o.d'.
# At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put
# dependencies in 'foo.d' instead, so we check for that too.
# Subdirectories are respected.
set_dir_from "$object"
set_base_from "$object"
if test "$libtool" = yes; then
# Libtool generates 2 separate objects for the 2 libraries. These
# two compilations output dependencies in $dir.libs/$base.o.d and
# in $dir$base.o.d. We have to check for both files, because
# one of the two compilations can be disabled. We should prefer
# $dir$base.o.d over $dir.libs/$base.o.d because the latter is
# automatically cleaned when .libs/ is deleted, while ignoring
# the former would cause a distcleancheck panic.
tmpdepfile1=$dir$base.o.d # libtool 1.5
tmpdepfile2=$dir.libs/$base.o.d # Likewise.
tmpdepfile3=$dir.libs/$base.d # Compaq CCC V6.2-504
"$@" -Wc,-MD
else
tmpdepfile1=$dir$base.d
tmpdepfile2=$dir$base.d
tmpdepfile3=$dir$base.d
"$@" -MD
fi
stat=$?
if test $stat -ne 0; then
rm -f "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
exit $stat
fi
for tmpdepfile in "$tmpdepfile1" "$tmpdepfile2" "$tmpdepfile3"
do
test -f "$tmpdepfile" && break
done
# Same post-processing that is required for AIX mode.
aix_post_process_depfile
;;
msvc7)
if test "$libtool" = yes; then
showIncludes=-Wc,-showIncludes
else
showIncludes=-showIncludes
fi
"$@" $showIncludes > "$tmpdepfile"
stat=$?
grep -v '^Note: including file: ' "$tmpdepfile"
if test $stat -ne 0; then
rm -f "$tmpdepfile"
exit $stat
fi
rm -f "$depfile"
echo "$object : \\" > "$depfile"
# The first sed program below extracts the file names and escapes
# backslashes for cygpath. The second sed program outputs the file
# name when reading, but also accumulates all include files in the
# hold buffer in order to output them again at the end. This only
# works with sed implementations that can handle large buffers.
sed < "$tmpdepfile" -n '
/^Note: including file: *\(.*\)/ {
s//\1/
s/\\/\\\\/g
p
}' | $cygpath_u | sort -u | sed -n '
s/ /\\ /g
s/\(.*\)/'"$tab"'\1 \\/p
s/.\(.*\) \\/\1:/
H
$ {
s/.*/'"$tab"'/
G
p
}' >> "$depfile"
echo >> "$depfile" # make sure the fragment doesn't end with a backslash
rm -f "$tmpdepfile"
;;
msvc7msys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
#nosideeffect)
# This comment above is used by automake to tell side-effect
# dependency tracking mechanisms from slower ones.
dashmstdout)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout, regardless of -o.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
test -z "$dashmflag" && dashmflag=-M
# Require at least two characters before searching for ':'
# in the target name. This is to cope with DOS-style filenames:
# a dependency such as 'c:/foo/bar' could be seen as target 'c' otherwise.
"$@" $dashmflag |
sed "s|^[$tab ]*[^:$tab ][^:][^:]*:[$tab ]*|$object: |" > "$tmpdepfile"
rm -f "$depfile"
cat < "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process this sed invocation
# correctly. Breaking it into two sed invocations is a workaround.
tr ' ' "$nl" < "$tmpdepfile" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
dashXmstdout)
# This case only exists to satisfy depend.m4. It is never actually
# run, as this mode is specially recognized in the preamble.
exit 1
;;
makedepend)
"$@" || exit $?
# Remove any Libtool call
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# X makedepend
shift
cleared=no eat=no
for arg
do
case $cleared in
no)
set ""; shift
cleared=yes ;;
esac
if test $eat = yes; then
eat=no
continue
fi
case "$arg" in
-D*|-I*)
set fnord "$@" "$arg"; shift ;;
# Strip any option that makedepend may not understand. Remove
# the object too, otherwise makedepend will parse it as a source file.
-arch)
eat=yes ;;
-*|$object)
;;
*)
set fnord "$@" "$arg"; shift ;;
esac
done
obj_suffix=`echo "$object" | sed 's/^.*\././'`
touch "$tmpdepfile"
${MAKEDEPEND-makedepend} -o"$obj_suffix" -f"$tmpdepfile" "$@"
rm -f "$depfile"
# makedepend may prepend the VPATH from the source file name to the object.
# No need to regex-escape $object, excess matching of '.' is harmless.
sed "s|^.*\($object *:\)|\1|" "$tmpdepfile" > "$depfile"
# Some versions of the HPUX 10.20 sed can't process the last invocation
# correctly. Breaking it into two sed invocations is a workaround.
sed '1,2d' "$tmpdepfile" \
| tr ' ' "$nl" \
| sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' \
| sed -e 's/$/ :/' >> "$depfile"
rm -f "$tmpdepfile" "$tmpdepfile".bak
;;
cpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
# Remove '-o $object'.
IFS=" "
for arg
do
case $arg in
-o)
shift
;;
$object)
shift
;;
*)
set fnord "$@" "$arg"
shift # fnord
shift # $arg
;;
esac
done
"$@" -E \
| sed -n -e '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
-e '/^#line [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' \
| sed '$ s: \\$::' > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
cat < "$tmpdepfile" >> "$depfile"
sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvisualcpp)
# Important note: in order to support this mode, a compiler *must*
# always write the preprocessed file to stdout.
"$@" || exit $?
# Remove the call to Libtool.
if test "$libtool" = yes; then
while test "X$1" != 'X--mode=compile'; do
shift
done
shift
fi
IFS=" "
for arg
do
case "$arg" in
-o)
shift
;;
$object)
shift
;;
"-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI")
set fnord "$@"
shift
shift
;;
*)
set fnord "$@" "$arg"
shift
shift
;;
esac
done
"$@" -E 2>/dev/null |
sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::\1:p' | $cygpath_u | sort -u > "$tmpdepfile"
rm -f "$depfile"
echo "$object : \\" > "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::'"$tab"'\1 \\:p' >> "$depfile"
echo "$tab" >> "$depfile"
sed < "$tmpdepfile" -n -e 's% %\\ %g' -e '/^\(.*\)$/ s::\1\::p' >> "$depfile"
rm -f "$tmpdepfile"
;;
msvcmsys)
# This case exists only to let depend.m4 do its work. It works by
# looking at the text of this script. This case will never be run,
# since it is checked for above.
exit 1
;;
none)
exec "$@"
;;
*)
echo "Unknown depmode $depmode" 1>&2
exit 1
;;
esac
exit 0
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:
mdk-1.3.1/intltool-extract.in 0000664 0001750 0001750 00000000000 15065042012 011577 mdk-1.3.1/mkinstalldirs 0000755 0001750 0001750 00000003704 14171035245 010564 #! /bin/sh
# mkinstalldirs --- make directory hierarchy
# Author: Noah Friedman
# Created: 1993-05-16
# Public domain
errstatus=0
dirmode=""
usage="\
Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..."
# process command line arguments
while test $# -gt 0 ; do
case $1 in
-h | --help | --h*) # -h for help
echo "$usage" 1>&2
exit 0
;;
-m) # -m PERM arg
shift
test $# -eq 0 && { echo "$usage" 1>&2; exit 1; }
dirmode=$1
shift
;;
--) # stop option processing
shift
break
;;
-*) # unknown option
echo "$usage" 1>&2
exit 1
;;
*) # first non-opt arg
break
;;
esac
done
for file
do
if test -d "$file"; then
shift
else
break
fi
done
case $# in
0) exit 0 ;;
esac
case $dirmode in
'')
if mkdir -p -- . 2>/dev/null; then
echo "mkdir -p -- $*"
exec mkdir -p -- "$@"
fi
;;
*)
if mkdir -m "$dirmode" -p -- . 2>/dev/null; then
echo "mkdir -m $dirmode -p -- $*"
exec mkdir -m "$dirmode" -p -- "$@"
fi
;;
esac
for file
do
set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'`
shift
pathcomp=
for d
do
pathcomp="$pathcomp$d"
case $pathcomp in
-*) pathcomp=./$pathcomp ;;
esac
if test ! -d "$pathcomp"; then
echo "mkdir $pathcomp"
mkdir "$pathcomp" || lasterr=$?
if test ! -d "$pathcomp"; then
errstatus=$lasterr
else
if test ! -z "$dirmode"; then
echo "chmod $dirmode $pathcomp"
lasterr=""
chmod "$dirmode" "$pathcomp" || lasterr=$?
if test ! -z "$lasterr"; then
errstatus=$lasterr
fi
fi
fi
fi
pathcomp="$pathcomp/"
done
done
exit $errstatus
# Local Variables:
# mode: shell-script
# sh-indentation: 2
# End:
# mkinstalldirs ends here
mdk-1.3.1/doc/ 0000775 0001750 0001750 00000000000 15065042311 006574 5 mdk-1.3.1/doc/MIX.DOC 0000644 0001750 0001750 00000062127 12112755472 007517 This has been lifted verbatim from Knuth volume 1. (See README for the
reference.) Some examples and witty but nonessential sections that I didn't
feel like typing have been omitted.
Copyright (C) 1973, 1968 by Addison-Wesley; used without permission.
1.3.1 Description of MIX.
...
MIX has a peculiar property in that it is both binary and decimal at the
same time. The programmer doesn't actually know whether he is programming a
machine with base 2 or base 10 arithmetic. ...
Words. The basic unit of information is a -byte-. Each byte contains an
-unspecified- amount of information, but it must be capable of holding at
least 64 distinct values. That is, we know that any number between 0 and
63, inclusive, can be contained in one byte. Furthermore, each byte
contains -at-most- 100 distinct values. On a binary computer a byte must
therefore be composed of six bits; on a decimal computer we have two digits
per byte.
... An algorithm in MIX should work properly regardless of how big a
byte is. Although it is quite possible to write programs which depend on
the byte size, this is an illegal act which will not be tolerated; the only
legitimate programs are those which would give correct results with all
byte sizes. ...
A computer word is five bytes plus a sign. The sign position has only
two possible values, + and -.
Registers. There are nine registers in MIX.
The A-register (Accumulator) is five bytes plus sign.
The X-register (Extension) is also five bytes plus sign.
The I-registers (Index registers) I1, I2, I3, I4, I5, and I6 each hold
two bytes plus sign.
The J-register (Jump address) holds two bytes, and its sign is always +.
We shall use a small letter ``r'' prefixed to the name, to identify a MIX
register. Thus, ``rA'' means ``register A''.
The A-register has many uses, especially for arithmetic and operating on
data. The X-register is an etension on the ``right-hand side'' of rA, and it
is used in connection with rA to hold ten bytes of a product or dividend, or
it can be used to hold information shifted to the right out of rA. The index
registers rI1, rI2, rI3, rI4, rI5, and rI6 are used primarily for counting and
for referencing variable memory addresses. The J-register always hold the
address of the instruction following the preceding ``JUMP'' intruction, and it
is primarily used in connection with subroutines.
Besides thesee registers, MIX contains
an overflow toggle (a single bit which is either ``on'' or ``off''),
a comparison indicator (which has three values: less, equal, or greater),
memory (4000 words of storage, each word with five bytes plus sign),
and input-output devices (cards, tapes, etc.).
Partial fields of words. The five bytes and sign of a computer word are
numbered as follows:
0 1 2 3 4 5
+/- Byte Byte Byte Byte Byte.
Most of the instructions allow the programmer to use only part of a word if he
chooses. In this case a ``field specification'' is given. The allowable
fields are those which are adjacent in a computer word, and they are
represented by (L:R), where L is the number of the left-hand part and R is the
number of the right-hand part of the field. Examples of field specifications
are:
(0:0), the sign only.
(0:2), the sign and first two bytes.
(0:5), the whole word. This is the most common field specification.
(1:5), the whole word except the sign.
(4:4), the fourth byte only.
(4:5), the two least significant bytes.
The use of these field specifications varies slightly from instruction to
instruction, and it will be explained in detail for each instruction where
it applies.
Although it is generally not important to the programmer, the field (L:R)
is denoted in the machine by the single number 8L + R, and this number will
fit in one byte.
Instruction format. Computer words used for instructions have the following
form:
0 1 2 3 4 5 (3)
+/- A A I F C.
The rightmost byte, C, is the operation code telling what operation is to
be performed. For example, C=8 is the operation LDA, ``load the A register''.
The F-byte holds a modification of the operation code. F is usually a
field specification (L:R)=8L + R; for example, if C=8 and F=11, the operation
is ``load the A-register with the (1:3) field''. Sometimes F is used for other
purposes; on input-output instructions, for example, F is the number of the
affected input or output unit.
The left-hand portion of the instruction, +/-AA, is the ``address''. (Note
that the sign is part of the address.) The I-field, which comes next to the
address, is the ``index specification'', which may be used to modify the
address of an instruction. If I=0, the address +/-AA is used without change;
otherwise I should contain a number {i} between 1 and 6, and the contents of
index register I{i} are added algebraically to +/-AA; the result is used as
the address of the instruction. this indexing process takes place on -every-
instruction. We will use the letter M to indicate the address after any
specified indexing has occurred. (If the addition of the index register to the
address +/-AA yields a result which does not fit in two bytes, the value of M
is undefined.)
In most instructions, M will refer to a memory cell. The terms ``memory
cell'' and ``memory location'' are used almost interchangeably in this book.
We assume that there are 4000 memory cells, numbered fro 0 to 3999; hence every
memory location can be addressed with two bytes. For every instruction in
which M is to refer to a memory cell we must have 0 <= M <= 3999, and in this
case we will write CONTENTS(M) to denote the value stored in memory location M.
On certain instructions, the ``address'' M has another significance, and it
may even be negative. Thus, one instruction adds M to an index register, and
this operation takes account of the sign of M.
Notation. To discuss instructions in a readable manner, we will use the
notation
OP ADDRESS,I(F) (4)
to denote an instruction like (3). Here OP is a symbolic name which is given
to the operation code (the C-part) of the instruction; ADDRESS is the +/-AA
portion; and I, F represent the I- and F-fields, respectively.
If I is zero, the ``,I'' is omitted. If F is the -normal- F-specification
for this particular operator, the ``(F)'' need not be written. The normal F-
specification for almost all operators is (0:5), representing a whole word.
If a different F is standard, it will be mentioned explicity when we discuss
a particular operator.
...
Rules for each instruction. The remarks following (3) above have defined the
quantities M, F, and C for every word used as an instruction. We will now
define the actions corresponding to each instruction. [Knuth gives C- and F-
values in each instruction's entry; I'm omitting them since you can get them
from the opcodes file in this distribution.]
Loading operators
* LDA (load A).
The specified field of CONTENTS(M) replaces the previous contents of register
A.
On all operations where a partial field is used as an input, the sign is
used if it is a part of the field, otherwise the sign + is understood. The
field is shifted over to the right-hand part of the register as it is loaded.
Examples: If F is the normal field specification (0:5), the entire contents
of location M is loaded. If F is (1:5), the absolute value of CONTENTS(M) is
loaded with a plus sign. If M contains an -instruction- word and if F is
(0:2), the ``+/-AA'' field is loaded as
0 1 2 3 4 5
+/- 0 0 0 A A.
...
* LDX (load X).
This is the same as LDA, except that rX is loaded instead of rA.
* LD{i} (load {i}).
This is the same as LDA, except that rI{i} is loaded instead of rA. An index
register contains only two bytes (not five) plus sign; bytes 1, 2, 3 are always
assumed to be zero. The LD{i} instruction is considered undefined if it would
result in setting bytes 1, 2, 3 to anything but zero.
In the description of all instructions, ``{i}'' stands for an integer,
1 <= i <= 6. Thus, LD{i} stands for six different instructions:
LD1, LD2, ..., LD6.
* LDAN (load A negative).
* LDXN (load X negative).
* LD{i}N (load {i} negative).
These eight instructions are the same as LDA, LDX, LD{i}, respectively, except
that the -opposite- sign is loaded.
Storing operators.
* STA (store A).
The contents of rA replaces the field of CONTENTS(M) specified by F. The other
parts of CONTENTS(M) are unchanged.
On a -store- operation the field F has the opposite significance from the
-load- operation. The number of bytes in the field is taken from the right-
hand side of the the register and shifted -left- if necessary to be inserted in
the proper field of CONTENTS(M). The sign is not altered unless it is part of
the field. The contents of the register is not affected.
...
* STX (store X).
Same as STA except rX is stored rather than rA.
* ST{i} (store {i}).
Same as STA except rI{i} is stored rather than rA. Bytes 1, 2, 3 of an index
register are zero; thus if rI1 contains
+/- m n
this behaves as though it were
0 1 2 3 4 5
+/- 0 0 0 m n.
* STJ (store J).
Same as ST{i} except rJ is stored, and its sign is always +.
On STJ the normal field specification for F is (0:2), -not- (0:5). This is
natural, since STJ is almost always done into the address field of an
instruction.
* STZ (store zero).
Same as STA except plus zero is stored. In other words, the specified field of
CONTENTS(M) is cleared to zero.
Arithmetic operators. On the add, subtract, multiply, and divide operations a
field specification is allowed. A field specification of ``(0:6)'' can be used
to indicate a ``floating-point'' operation (see Section 4.2 [in Volume 2]), but
few of the programs we will write for MIX will use this feature...
The standard field specification is, as usual, (0:5). Other fields are
treated as in LDA. We will use the letter V to indicate the specified field of
CONTENTS(M); thus, V is the value which would have been loaded into register A
if the operation code were LDA.
* ADD.
V is added to rA. If the magnitude of the result is too large for register A,
the overflow toggle is set on, and the remainder of the addition appearing in
rA is as though a ``1'' had been carried into another register to the left of
A. (Otherwise the setting of the overflow toggle is unchanged.) If the result
is zero, the sign of rA is unchanged.
Example: The sequence of instructions below gives the sum of the five
bytes of register A.
STA 2000
LDA 2000(5:5)
ADD 2000(4:4)
ADD 2000(3:3)
ADD 2000(2:2)
ADD 2000(1:1)
This is sometimes called ``sideways addition''.
* SUB (subtract).
V is subtracted from rA. Overflow may occur as in ADD.
Note that because of the variable definition of byte size, overflow will
occur in some MIX computers when it would not occur in others...
* MUL (multiply).
The 10-byte product of V times (rA) replaces registers A and X. The signs of
rA and rX are both set to the algebraic sign of the result (i.e., + if the
signs of V and rA were the same, and - if they were different).
* DIV (divide).
The value of rA and rX, treated as a 10-byte number, with the sign of rA, is
divided by the value V. If V=0 or if the quotient is more than five bytes in
magnitude (this is equivalent to the condition that |rA| >= |V|), registers A
and X are filled with undefined information and the overflow toggle is set on.
Otherwise the quotient is placed in rA and the remainder is placed in rX. The
sign of rA afterward is the algebraic sign of the quotient; the sign of rX
afterward is the previous sign of rA.
...
Address transfer operators. In the following operations, the (possibly
indexed) ``address'' M is used as a signed number, not as the address of a
cell in memory.
* ENTA (enter A).
The quantity M is loaded into rA. The action is equivalent to ``LDA'' from a
memory word containing the signed value of M. If M=0, the sign of the
instruction is loaded. [I don't think the simulator works that way. Better
check...]
Examples: ``ENTA 0'' sets rA to zeros. ``ENTA 0,1'' sets rA to the current
contents of index register 1, except that -0 is changed to +0.
* ENTX (enter X).
* ENT{i} (enter {i}).
Analogous to ENTA, loading the appropriate register.
* ENNA (enter negative A).
* ENNX (enter negative X).
* ENN{i} (enter negative {i}).
Same as ENTA, ENTX, and ENT{i}, except that the opposite sign is loaded.
Example: ``ENN3 0,3'' replaces rI3 by its negative.
* INCA (increase A).
The quantity M is added to rA; the action is equivalent to ``ADD'' from a
memory word containing the value of M. Overflow is possible and it is treated
just as in ADD.
Example: ``INCA 1'' increases the value of rA by one.
* INCX (increase X).
The quantity M is added to rX. If overflow occurs, the action is equivalent to
ADD, except that rX is used instead of rA. Register A is never affected by
this instruction.
* INC{i} (increase {i}).
Add M to rI{i}. Overflow must not occur; if the magnitude of the result is
more than two bytes, the result of this instruction is undefined.
* DECA (decrease A).
* DECX (decrease X).
* DEC{i} (decrease {i}).
These eight instructions are the same as INCA, INCX, and INC{i}, respectively,
except that M is subtracted from the register rather than added.
Note that the operation code C is the same for ENTA, ENNA, INCA, AND DECA;
the F-field is used to distinguish the various operations in this case.
Comparison operators. The comparison operators all compare the value contained
in a register with a value contained in memory. The comparison indicator is
then set to LESS, EQUAL, or GREATER according to whether the value of the
-register- is less than, equal to, or greater than the value of the -memory-
-cell-. A minus zero is -equal-to- a plus zero.
* CMPA (compare A).
The specified field of A is compared with the -same- field of CONTENTS(M). If
the field F does not include the sign position, the fields are both thought of
as positive; otherwise the sign is taken into account in the comparison. (If
F is (0:0) an equal comparison always occurs, since minus zero equals plus
zero.)
* CMPX (compare X).
This is analogous to CMPA.
* CMP{i} (compare {i}).
Analogous to CMPA. Bytes 1, 2, and 3 of the index register are treated as
zero in the comparison. (Thus if F = (1:2), the result cannot be GREATER.)
Jump operators. Ordinarily, instructions are executed in sequential oder;
i.e., the instruction executed after the one in location P is the instruction
found in location P+1. Several ``jump'' instructions allow this sequence to
be interrupted. When such a jump takes place, the J-register is normally set
to the address of the next instruction (that is, the address of the instruction
which would have been next if we hadn't jumped). A ``store J'' instruction
then can be used by the programmer, if desired, to set the address field of
another command which will later be used to return to the original place in the
program. The J-register is changed whenever a jump actually occurs in a
program (except JSJ), and it is never changed except when a jump occurs.
* JMP (jump).
Unconditional jump: the next instruction is taken from location M.
* JSJ (jump, save J).
Same as JMP except that the contents of rJ are unchanged.
* JOV (jump on overflow).
If the overflow toggle is on, it is turned off and a JMP occurs; otherwise
nothing happens.
* JNOV (jump on no overflow).
If the overflow toggle is off, a JMP occurs; otherwise it is turned off.
* JL, JE, JG, JGE, JNE, JLE (jump on less, equal, greater, greater-or-equal,
unequal, less-or-equal).
Jump if the comparison indicator is set to the condition indicated. For
example, JNE will jump if the comparison indicator is LESS or GREATER. The
comparison indicator is not changed by these instructions.
* JAN, JAZ, JAP, JANN, JANZ, JANP (jump A negative, zero, positive,
nonnegative, nonzero, nonpositive).
If the contents of rA satisfy the stated condition, a JMP occurs, otherwise
nothing happens. ``Positive'' means -greater- than zero (not zero);
``nonpositive'' means the opposite, i.e., zero or negative.
* JXN, JXZ, JXP, JXNN, JXNZ, JXNP (jump X negative, zero, positive,
nonnegative, nonzero, nonpositive).
* J{i}N, J{i}Z, J{i}P, J{i}NN, J{i}NZ, J{i}NP (jump {i} negative, zero, positive,
nonnegative, nonzero, nonpositive).
These are analogous to the corresponding operations for rA.
Miscellaneous operators.
* MOVE.
The number of words specified by F is moved, starting from location M to the
location specified by the contents of index register 1. The transfer occurs
one word at a time, and rI1 is increased by the value of F at the end of the
operation. If F=0, nothing happens.
Care must be taken when the groups of locations involved overlap...
* SLA, SRA, SLAX, SRAX, SLC, SRC (shift left A, shift right A, shift left AX,
shift right AX, shift left AX circularly, shift right AX circularly).
These are the ``shift'' commands. Signs of registers A, X are not affected
in any way. M specifies the number of -bytes- to be shifted left or right; M
must be nonnegative. SLA and SRA do not affect rX; the other shifts affect
both registers as though they were a single 10-byte register. With SLA, SRA,
SLAX, and SRAX, zeros are shifted into the register at one side, and bytes
disappear at the other side. The instructions SLC and SRC call for a
``circulating'' shift, in which the bytes that leave one end enter in at the
other end. Both rA and rX participate in a circulating shift.
Examples:
Register A Register X
Initial contents + 1 2 3 4 5 - 6 7 8 9 10
SRAX 1 + 0 1 2 3 4 - 5 6 7 8 9
SLA 2 + 2 3 4 0 0 - 5 6 7 8 9
SRC 4 + 6 7 8 9 2 - 3 4 0 0 5
SRA 2 + 0 0 6 7 8 - 3 4 0 0 5
SLC 501 + 0 6 7 8 3 - 4 0 0 5 0
* NOP (no operation).
No operation occurs, and this instruction is bypassed. F and M are ignored.
* HLT (halt).
The machine stops. When the computer operator restarts it, the net effect is
equivalent to NOP.
Input-output operators. MIX has a fair amount of input-output equipment (all
of which is optional at extra cost). Each device is given a number as follows:
Unit number Peripheral device Block size
t Tape unit no. t (0 <= t <= 7) 100 words
d Disk or drum unit no. d (8 <= d <= 15) 100 words
16 Card reader 16 words
17 Card punch 16 words
18 Printer 24 words
19 Typewriter and paper tape 14 words
Not every MIX installation will have all of this equipment available; we will
occasionally make appropriate assumptions about the presence of certain
devices. Some devices may not be used both for input and for output. The
number of words mentioned in the above tble is a fixed block size associated
with each unit.
Input or output with magnetic tape, disk, or drum units reads or writes
full words (five bytes plus sign). Input or output with units 16 through 19,
however, is always done in a -character-code- where each byte represents one
alphnumeric character. Thus, five characters per MIX word are transmitted.
The character code is given [in charset.c]... It is not possible to read in
or write out all possible values a byte may have, since certain combinations
are undefined. Not all input-output devices are capable of handling all the
symbols in the character set; for example, the symbols phi and pi which appear
amid the letters will perhaps not be acceptable to the card reader. When input
of character code is being done, the signs of all words are set to ``+''; on
output, signs are ignored.
The disk and drum units are large external memory devices each containing
b^2 100-word blocks, where b is the byte size. On every IN, OUT, or IOC
instruction as defined below, the particular 100-word block referred to by the
instruction is specified by the current contents of the two least significant
bytes of rX.
* IN (input). C=36; F=unit.
This instruction initiates the transfer of information from the input unit
specified into consecutive locations starting with M. The number of locations
transferred is the block size for this unit (see the table above). The machine
will wait at this point if a preceding operation for the same unit is not yet
complete. The transfer of information which starts with this instruction will
not be complete until somewhat later, depending on the speed of the input
device, so a program must not refer to the information in memory until then.
It is improper to attempt to read any record from magnetic tape which follows
the latest record written on that tape.
* OUT (output). C=37; F=unit.
This instruction starts the transfer of information from memory locations
starting at M to the output unit specified. (The machine waits until the unit
is ready, if it is not initially ready.) The transfer will not be complete
until somewhat later, depending on the speed of the output device, so a program
must not alter the information in memory until then.
* IOC (input-output control). C=35; F=unit.
The machine waits, if necessary, until the specified unit is not busy. Then a
control operation is performed, depending on the particular device being used.
The following examples are used in various parts of this book:
Magnetic tape: If M=0, the tape is rewound. If M<0 the tape is skipped
backward -M records, or to the beginning of the tape, whichever comes first.
If M>0, the tape is skipped forward; it is improper to skip forward over any
records following the one last written on that tape.
For example, the sequence ``OUT 100(3); IOC -1(3); IN 2000(3)'' writes out
one hundred words onto tape 3, then reads it back in again. Unless the tape
reliability is questioned, the last two instructions of that sequence are only
a slow way to move words 1000-1099 to locations 2000-2099. The sequence
``OUT 1000(3); IOC +1(3)'' is improper.
Disk or drum: M should be zero. The effect is to position the device
according to rX so that the next IN or OUT operation on this unit will take
less time if it uses the same rX setting.
Printer: M should be zero. ``IOC 0(18)'' skips the printer to the top of
the following page.
Paper tape reader: Rewind the tape. (M should be zero).
* JRED (jump ready). C=38; F=unit.
A jump occurs if the specified unit is ready, i.e., finished with the preceding
operation initiated by IN, OUT, or IOC.
* JBUS (jump busy). C=34; F=unit.
Same as JRED except the jump occurs under the opposite circumstances, i.e.,
when the specified unit is -not- ready.
Example: In location 1000, the instruction ``JBUS 1000(16)'' will be
executed repeatedly until unit 16 is ready.
The simple operations above complete MIX's repertoire of input-output
instructions. There is no ``tape check'' indicator, etc...
Conversion Operators.
* NUM (convert to numeric).
This operation is used to change the character code into numeric code. M is
ignored. Registers A, X are assumed to contain a 10-byte number in character
code; the NUM instruction sets the magnitude of rA equal to the numerical value
of this number (treated as a decimal number). The value of rX and the sign of
rA are unchanged. Bytes 00, 10, 20, 30, 40, ... convert to the digit zero;
bytes 01, 11, 21, ... convert to the digit one; etc. Overflow is possible, and
in this case the remainder modulo the word size is retained.
* CHAR (convert to characters).
This operation is used to change numeric code into character code suitable for
output to cards or printer. The value in rA is converted into a 10-byte
decimal number which is put into register A and X in character code. The signs
of rA, rX are unchanged. M is ignored.
...
Timing. To give quantitative information as to how ``good'' MIX programs are,
each of MIX's operations is assigned an execution time typical for present-day
computers.
ADD, SUB, all LOAD operations, all STORE operations (including STZ), all
shift commands, and all comparison operations take two units of time. MOVE
requires one unit plus two for each word moved. MUL requires 10 and DIV
requires 12 units. Execution time for floating-point operations is
unspecified. All remaining operations take one unit of time, plus the time
the computer may be idle on the IN, OUT, IOC, or HLT instructions.
Note in particular that ENTA takes on unit of time, while LDA takes two
units. The timing rules are easily remembered because of the fact that, except
for shifts, MUL, and DIV, the number of units equals the number of references
to memory (including the reference to the instruction itself).
The ``unit'' of time is a relative measure which we will denote simply by
u. It may be regarded as, say, 10 microseconds (for a relatively inexpensive
computer) or as 1 microsecond (for a relatively high-priced machine).
Example: the sequence LDA 1000; INCA 1; STA 1000 takes exactly 5u.
mdk-1.3.1/doc/mdk_emacs.texi 0000644 0001750 0001750 00000012636 10770465100 011343 @c -*-texinfo-*-
@c This is part of the GNU MDK Reference Manual.
@c Copyright (C) 2003, 2004
@c Free Software Foundation, Inc.
@c See the file mdk.texi for copying conditions.
@node Emacs tools, mixasm, Getting started, Top
@chapter Emacs tools
Everyone writing code knows how important a good editor is. Most
systems already come with Emacs, and excellent programmer's editor.
@sc{mdk} adds support to Emacs for both writing and debugging MIX
programs. A major mode for MIXAL source files eases edition of your
code, while integration with Emacs' debugging interface
(@acronym{GUD}) lets you use @code{mixvm} without leaving your
favourite text editor.
This chapter shows how to use the Elisp modules included in @sc{mdk},
assuming that you have followed the installation instructions in
@xref{Emacs support}.
@menu
* MIXAL mode:: Editing MIXAL files.
* GUD integration:: Invoking @code{mixvm} within Emacs.
@end menu
@node MIXAL mode, GUD integration, Emacs tools, Emacs tools
@section MIXAL mode
The module @file{mixal-mode.el} provides a new mode, mixal-mode, for
editing MIXAL source files@footnote{mixal-mode has been developed and
documented by @value{PIETER}}. When everything is installed correctly,
Emacs will select it as the major mode for editing files with extension
@code{.mixal}. You can also activate mixal-mode in any buffer
issuing the Emacs command @code{M-x mixal-mode}.
@menu
* Basics:: Editing code, font locking and indentation.
* Help system:: Using the interactive help system.
* Compiling and running:: Invoking compiler and/or virtual machine.
@end menu
@node Basics, Help system, MIXAL mode, MIXAL mode
@comment node-name, next, previous, up
@subsection Basics
The mode for editing mixal source files is inherited from
fundamental-mode, meaning that all your favorite editing operations
will still work. If you want a short introduction to Emacs, type
@kbd{C-h t} inside Emacs to start the tutorial.
Mixal mode adds font locking. If you do not have font locking globally
enabled, you can turn it on for mixal-mode by placing the following
line in your @file{.emacs} file:
@lisp
(add-hook 'mixal-mode-hook 'turn-on-font-lock)
@end lisp
You can also customize the colors used to colour your mixal code by
changing the requisite faces. This is the list of faces used by
mixal-mode:
@itemize
@item @var{font-lock-comment-face}
Face to use for comments.
@item @var{mixal-font-lock-label-face}
Face to use for label names.
@item @var{mixal-font-lock-operation-code-face}
Face to use for operation code names.
@item @var{mixal-font-lock-assembly-pseudoinstruction-face}
Face to use for assembly pseudo-instruction names.
@end itemize
@node Help system, Compiling and running, Basics, MIXAL mode
@comment node-name, next, previous, up
@subsection Help system
When coding your program, you will be thinking, looking up
documentation and editing files. Emacs already helps you with editing
files, but Emacs can do much more. In particular, looking up
documentation is one of its strong points. Besides the info system
(which you are probably already using), mixal-mode defines commands
for getting particular information about a MIX operation code.
With @kbd{M-x mixal-describe-operation-code} (or its keyboard shortcut
@kbd{C-h o}) you will get the documentation about a particular MIX
operation code. Keep in mind that these are not assembly (MIXAL)
pseudoinstructions. When the @code{point} is around a MIXAL
pseudoinstruction in your source file, Emacs will recognize it and
will suggest the right MIX operation code.
@node Compiling and running, , Help system, MIXAL mode
@comment node-name, next, previous, up
@subsection Compiling and running
After you have written your MIXAL program, you'll probably want to
test it. This can be done with the MIX virtual machine. First you will
need to compile your code into MIX byte code. This can be done within
Emacs with the command @kbd{M-x compile} (@kbd{C-c c}). In case of
compilation errors, you can jump to the offending source code line
with @kbd{M-x next-error}.
Once the program compiles without errors, you can debug or run
it. To invoke the debugger, use @kbd{M-x mixal-debug} (@kbd{C-c d}).
Emacs will open a @code{GUD} buffer where you can
use the debugging commands described in @xref{mixvm}.
If you just want to execute the program, you can do so with @kbd{M-x
mixal-run} (@kbd{C-c r}). This will invoke mixvm,
execute the program and show its output in a separate buffer.
@node GUD integration, , MIXAL mode, Emacs tools
@section GUD integration
If you are an Emacs user and write your MIXAL programs using this
editor, you will find the elisp program @file{mixvm.el} quite
useful@footnote{@file{mixvm.el} has been kindly contributed by
@value{PHILIP}. @file{mixvm.el} is based on a study of gdb, perldb, and
pdb as found in @file{gud.el}, and @file{rubydb3x.el} distributed with
the source code to the Ruby language.}. @file{mixvm.el} allows running
the MIX virtual machine @code{mixvm} (@pxref{mixvm}) inside an Emacs
@acronym{GUD} buffer, while visiting the MIXAL source file in another
buffer.
After installing @file{mixvm.el} (@pxref{Emacs support}), you can
initiate an @sc{mdk}/@acronym{GUD} session inside Emacs with the command
@example
M-x mixvm
@end example
@noindent
and you will have a @code{mixvm} prompt inside a newly created
@acronym{GUD} buffer. @acronym{GUD} will reflect the current line in the
corresponding source file buffer.
mdk-1.3.1/doc/mdk_mixasm.texi 0000644 0001750 0001750 00000005315 12622455635 011557 @c -*-texinfo-*-
@c This is part of the GNU MDK Reference Manual.
@c Copyright (C) 2000, 2001, 2003, 2004, 2006
@c Free Software Foundation, Inc.
@c See the file mdk.texi for copying conditions.
@node mixasm, mixvm, Emacs tools, Top
@comment node-name, next, previous, up
@chapter @code{mixasm}, the MIXAL assembler
@cindex @code{mixasm}
@cindex MIXAL
@cindex assembler
MIX programs, as executed by @code{mixvm}, are composed of binary
instructions loaded into the virtual machine memory as MIX
words. Although you could write your MIX programs directly as a series
of words in binary format, you have at your disposal a more friendly
assembly language, MIXAL (@pxref{MIXAL}) which is compiled into binary
form by @code{mixasm}, the MIXAL assembler included in @sc{mdk}. In this
chapter, you will find a complete description of @code{mixasm} options.
@menu
* Invoking mixasm::
@end menu
@node Invoking mixasm, , mixasm, mixasm
@comment node-name, next, previous, up
@section Invoking @code{mixasm}
In its simplest form, @code{mixasm} is invoked with a single argument,
which is the name of the MIXAL file to be compiled, e.g.
@example
mixasm hello
@end example
@noindent
will compile either @file{hello} or @file{hello.mixal}, producing a
binary file named @file{hello.mix} if no errors are found.
In addition, @code{mixasm} can be invoked with the following command
line options (note, that, following GNU's conventions, we provide a long
option name for each available single letter switch):
@example
mixasm [-vhulO] [-o OUTPUT_FILE] [--version] [--help] [--usage]
[--ndebug] [--output=OUTPUT_FILE] [--list[=LIST_FILE]] file
@end example
@noindent
The meaning of these options is as follows:
@defopt -v
@defoptx --version
Prints version and copyleft information and exits.
@end defopt
@defopt -h
@defoptx --help
@defoptx -u
@defoptx --usage
Prints a summary of available options and exits.
@end defopt
@defopt -O
@defoptx --ndebug
Do not include debugging information in the compiled file, saving
space but disallowing breakpoint setting at source level and symbol
table inspection under @code{mixvm}.
@end defopt
@defopt -o output_file
@defoptx --output=output_file
By default, the given source file @var{file.mixal} is compiled into
@var{file.mix}. You can provide a different name for the output file
using this option.
@end defopt
@defopt -l
@defoptx @w{--list[=list_file]}
@cindex .mls file
This option causes @code{mixasm} to produce, in addition to the
@file{.mix} file, an ASCII file containing a summary of the compilation
results. The file is named after the MIXAL source file, changing its
extension to @file{.mls} if no argument is provided; otherwise, the
listing file is named according to the argument.
@end defopt
mdk-1.3.1/doc/COPYING.MIX.DOC 0000644 0001750 0001750 00000001363 12112755472 010621 The file MIX.DOC, as well as the samples in elevator.mixal and mistery.mixal
are a contribution from Eric S. Raymond's MIXAL. They contain the actual
text of TAOCP vol 1 describing MIXAL and two verbatim programs from the book.
Donald Knuth and Addison Wesley granted Eric permission for distributing the
under the following terms, which we inherit:
The source code in prime.mix, mystery.mix, and elevator.mix and the
text in MIX.DOC are excerpted from "The Art Of Computer Programming".
Addison-Wesley and Donald Knuth have specifically granted permission
for this material and all other MIX code examples from that book to be
distributed in conjunction with any open-source implementation of MIX
under the license(s) applying to that implementation.
mdk-1.3.1/doc/mdk_index.texi 0000644 0001750 0001750 00000000505 12112755472 011360 @c -*-texinfo-*-
@c This is part of the GNU MDK Reference Manual.
@c Copyright (C) 2000, 2001, 2003, 2004, 2006
@c Free Software Foundation, Inc.
@c See the file mdk.texi for copying conditions.
@node Concept Index, Instructions and commands, Copying, Top
@unnumbered Concept Index
@cindex tail recursion
@printindex cp
mdk-1.3.1/doc/texinfo.tex 0000644 0001750 0001750 00001351025 14767572401 010737 % texinfo.tex -- TeX macros to handle Texinfo files.
%
% Load plain if necessary, i.e., if running under initex.
\expandafter\ifx\csname fmtname\endcsname\relax\input plain\fi
%
\def\texinfoversion{2024-02-10.22}
%
% Copyright 1985, 1986, 1988, 1990-2024 Free Software Foundation, Inc.
%
% This texinfo.tex file is free software: you can redistribute it and/or
% modify it under the terms of the GNU General Public License as
% published by the Free Software Foundation, either version 3 of the
% License, or (at your option) any later version.
%
% This texinfo.tex file is distributed in the hope that it will be
% useful, but WITHOUT ANY WARRANTY; without even the implied warranty
% of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
% General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with this program. If not, see .
%
% As a special exception, when this file is read by TeX when processing
% a Texinfo source document, you may use the result without
% restriction. This Exception is an additional permission under section 7
% of the GNU General Public License, version 3 ("GPLv3").
%
% Please try the latest version of texinfo.tex before submitting bug
% reports; you can get the latest version from:
% https://ftp.gnu.org/gnu/texinfo/ (the Texinfo release area), or
% https://ftpmirror.gnu.org/texinfo/ (same, via a mirror), or
% https://www.gnu.org/software/texinfo/ (the Texinfo home page)
% The texinfo.tex in any given distribution could well be out
% of date, so if that's what you're using, please check.
%
% Send bug reports to bug-texinfo@gnu.org. Please include a
% complete document in each bug report with which we can reproduce the
% problem. Patches are, of course, greatly appreciated.
%
% To process a Texinfo manual with TeX, it's most reliable to use the
% texi2dvi shell script that comes with the distribution. For a simple
% manual foo.texi, however, you can get away with this:
% tex foo.texi
% texindex foo.??
% tex foo.texi
% tex foo.texi
% dvips foo.dvi -o # or whatever; this makes foo.ps.
% The extra TeX runs get the cross-reference information correct.
% Sometimes one run after texindex suffices, and sometimes you need more
% than two; texi2dvi does it as many times as necessary.
%
% It is possible to adapt texinfo.tex for other languages, to some
% extent. You can get the existing language-specific files from the
% full Texinfo distribution.
%
% The GNU Texinfo home page is https://www.gnu.org/software/texinfo.
\message{Loading texinfo [version \texinfoversion]:}
% LaTeX's \typeout. This ensures that the messages it is used for
% are identical in format to the corresponding ones from latex/pdflatex.
\def\typeout{\immediate\write17}%
\chardef\other=12
% We never want plain's \outer definition of \+ in Texinfo.
% For @tex, we can use \tabalign.
\let\+ = \relax
% Save some plain tex macros whose names we will redefine.
\let\ptexb=\b
\let\ptexbullet=\bullet
\let\ptexc=\c
\let\ptexcomma=\,
\let\ptexdot=\.
\let\ptexdots=\dots
\let\ptexend=\end
\let\ptexequiv=\equiv
\let\ptexexclam=\!
\let\ptexfootnote=\footnote
\let\ptexgtr=>
\let\ptexhat=^
\let\ptexi=\i
\let\ptexindent=\indent
\let\ptexinsert=\insert
\let\ptexlbrace=\{
\let\ptexless=<
\let\ptexnewwrite\newwrite
\let\ptexnoindent=\noindent
\let\ptexplus=+
\let\ptexraggedright=\raggedright
\let\ptexrbrace=\}
\let\ptexslash=\/
\let\ptexsp=\sp
\let\ptexstar=\*
\let\ptexsup=\sup
\let\ptext=\t
\let\ptextop=\top
{\catcode`\'=\active \global\let\ptexquoteright'}% active in plain's math mode
% If this character appears in an error message or help string, it
% starts a new line in the output.
\newlinechar = `^^J
% Use TeX 3.0's \inputlineno to get the line number, for better error
% messages, but if we're using an old version of TeX, don't do anything.
%
\ifx\inputlineno\thisisundefined
\let\linenumber = \empty % Pre-3.0.
\else
\def\linenumber{l.\the\inputlineno:\space}
\fi
% Set up fixed words for English if not already set.
\ifx\putwordAppendix\undefined \gdef\putwordAppendix{Appendix}\fi
\ifx\putwordChapter\undefined \gdef\putwordChapter{Chapter}\fi
\ifx\putworderror\undefined \gdef\putworderror{error}\fi
\ifx\putwordfile\undefined \gdef\putwordfile{file}\fi
\ifx\putwordin\undefined \gdef\putwordin{in}\fi
\ifx\putwordIndexIsEmpty\undefined \gdef\putwordIndexIsEmpty{(Index is empty)}\fi
\ifx\putwordIndexNonexistent\undefined \gdef\putwordIndexNonexistent{(Index is nonexistent)}\fi
\ifx\putwordInfo\undefined \gdef\putwordInfo{Info}\fi
\ifx\putwordInstanceVariableof\undefined \gdef\putwordInstanceVariableof{Instance Variable of}\fi
\ifx\putwordMethodon\undefined \gdef\putwordMethodon{Method on}\fi
\ifx\putwordNoTitle\undefined \gdef\putwordNoTitle{No Title}\fi
\ifx\putwordof\undefined \gdef\putwordof{of}\fi
\ifx\putwordon\undefined \gdef\putwordon{on}\fi
\ifx\putwordpage\undefined \gdef\putwordpage{page}\fi
\ifx\putwordsection\undefined \gdef\putwordsection{section}\fi
\ifx\putwordSection\undefined \gdef\putwordSection{Section}\fi
\ifx\putwordsee\undefined \gdef\putwordsee{see}\fi
\ifx\putwordSee\undefined \gdef\putwordSee{See}\fi
\ifx\putwordShortTOC\undefined \gdef\putwordShortTOC{Short Contents}\fi
\ifx\putwordTOC\undefined \gdef\putwordTOC{Table of Contents}\fi
%
\ifx\putwordMJan\undefined \gdef\putwordMJan{January}\fi
\ifx\putwordMFeb\undefined \gdef\putwordMFeb{February}\fi
\ifx\putwordMMar\undefined \gdef\putwordMMar{March}\fi
\ifx\putwordMApr\undefined \gdef\putwordMApr{April}\fi
\ifx\putwordMMay\undefined \gdef\putwordMMay{May}\fi
\ifx\putwordMJun\undefined \gdef\putwordMJun{June}\fi
\ifx\putwordMJul\undefined \gdef\putwordMJul{July}\fi
\ifx\putwordMAug\undefined \gdef\putwordMAug{August}\fi
\ifx\putwordMSep\undefined \gdef\putwordMSep{September}\fi
\ifx\putwordMOct\undefined \gdef\putwordMOct{October}\fi
\ifx\putwordMNov\undefined \gdef\putwordMNov{November}\fi
\ifx\putwordMDec\undefined \gdef\putwordMDec{December}\fi
%
\ifx\putwordDefmac\undefined \gdef\putwordDefmac{Macro}\fi
\ifx\putwordDefspec\undefined \gdef\putwordDefspec{Special Form}\fi
\ifx\putwordDefvar\undefined \gdef\putwordDefvar{Variable}\fi
\ifx\putwordDefopt\undefined \gdef\putwordDefopt{User Option}\fi
\ifx\putwordDeffunc\undefined \gdef\putwordDeffunc{Function}\fi
% Give the space character the catcode for a space.
\def\spaceisspace{\catcode`\ =10\relax}
% Likewise for ^^M, the end of line character.
\def\endlineisspace{\catcode13=10\relax}
\chardef\dashChar = `\-
\chardef\slashChar = `\/
\chardef\underChar = `\_
% Ignore a token.
%
\def\gobble#1{}
% The following is used inside several \edef's.
\def\makecsname#1{\expandafter\noexpand\csname#1\endcsname}
% Hyphenation fixes.
\hyphenation{
Flor-i-da Ghost-script Ghost-view Mac-OS Post-Script
ap-pen-dix bit-map bit-maps
data-base data-bases eshell fall-ing half-way long-est man-u-script
man-u-scripts mini-buf-fer mini-buf-fers over-view par-a-digm
par-a-digms rath-er rec-tan-gu-lar ro-bot-ics se-vere-ly set-up spa-ces
spell-ing spell-ings
stand-alone strong-est time-stamp time-stamps which-ever white-space
wide-spread wrap-around
}
% Sometimes it is convenient to have everything in the transcript file
% and nothing on the terminal. We don't just call \tracingall here,
% since that produces some useless output on the terminal. We also make
% some effort to order the tracing commands to reduce output in the log
% file; cf. trace.sty in LaTeX.
%
\def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
\def\loggingall{%
\tracingstats2
\tracingpages1
\tracinglostchars2 % 2 gives us more in etex
\tracingparagraphs1
\tracingoutput1
\tracingmacros2
\tracingrestores1
\showboxbreadth\maxdimen \showboxdepth\maxdimen
\ifx\eTeXversion\thisisundefined\else % etex gives us more logging
\tracingscantokens1
\tracingifs1
\tracinggroups1
\tracingnesting2
\tracingassigns1
\fi
\tracingcommands3 % 3 gives us more in etex
\errorcontextlines16
}%
% @errormsg{MSG}. Do the index-like expansions on MSG, but if things
% aren't perfect, it's not the end of the world, being an error message,
% after all.
%
\def\errormsg{\begingroup \indexnofonts \doerrormsg}
\def\doerrormsg#1{\errmessage{#1}}
% add check for \lastpenalty to plain's definitions. If the last thing
% we did was a \nobreak, we don't want to insert more space.
%
\def\smallbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\smallskipamount
\removelastskip\penalty-50\smallskip\fi\fi}
\def\medbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\medskipamount
\removelastskip\penalty-100\medskip\fi\fi}
\def\bigbreak{\ifnum\lastpenalty<10000\par\ifdim\lastskip<\bigskipamount
\removelastskip\penalty-200\bigskip\fi\fi}
% Output routine
%
% For a final copy, take out the rectangles
% that mark overfull boxes (in case you have decided
% that the text looks ok even though it passes the margin).
%
\def\finalout{\overfullrule=0pt }
% Output a mark which sets \thischapter, \thissection and \thiscolor.
% We dump everything together because we only have one kind of mark.
% This works because we only use \botmark / \topmark, not \firstmark.
%
% A mark contains a subexpression of the \ifcase ... \fi construct.
% \get*marks macros below extract the needed part using \ifcase.
%
% Another complication is to let the user choose whether \thischapter
% (\thissection) refers to the chapter (section) in effect at the top
% of a page, or that at the bottom of a page.
% \domark is called twice inside \chapmacro, to add one
% mark before the section break, and one after.
% In the second call \prevchapterdefs is the same as \currentchapterdefs,
% and \prevsectiondefs is the same as \currentsectiondefs.
% Then if the page is not broken at the mark, some of the previous
% section appears on the page, and we can get the name of this section
% from \firstmark for @everyheadingmarks top.
% @everyheadingmarks bottom uses \botmark.
%
% See page 260 of The TeXbook.
\def\domark{%
\toks0=\expandafter{\currentchapterdefs}%
\toks2=\expandafter{\currentsectiondefs}%
\toks4=\expandafter{\prevchapterdefs}%
\toks6=\expandafter{\prevsectiondefs}%
\toks8=\expandafter{\currentcolordefs}%
\mark{%
\the\toks0 \the\toks2 % 0: marks for @everyheadingmarks top
\noexpand\or \the\toks4 \the\toks6 % 1: for @everyheadingmarks bottom
\noexpand\else \the\toks8 % 2: color marks
}%
}
% \gettopheadingmarks, \getbottomheadingmarks,
% \getcolormarks - extract needed part of mark.
%
% \topmark doesn't work for the very first chapter (after the title
% page or the contents), so we use \firstmark there -- this gets us
% the mark with the chapter defs, unless the user sneaks in, e.g.,
% @setcolor (or @url etc.) between @contents and the very first @chapter.
\def\gettopheadingmarks{%
\ifcase0\the\savedtopmark\fi
\ifx\thischapter\empty \ifcase0\firstmark\fi \fi
}
\def\getbottomheadingmarks{\ifcase1\botmark\fi}
\def\getcolormarks{\ifcase2\the\savedtopmark\fi}
% Avoid "undefined control sequence" errors.
\def\currentchapterdefs{}
\def\currentsectiondefs{}
\def\currentsection{}
\def\prevchapterdefs{}
\def\prevsectiondefs{}
\def\currentcolordefs{}
% Margin to add to right of even pages, to left of odd pages.
\newdimen\bindingoffset
\newdimen\normaloffset
\newdimen\txipagewidth \newdimen\txipageheight
% Main output routine.
%
\chardef\PAGE = 255
\newtoks\defaultoutput
\defaultoutput = {\savetopmark\onepageout{\pagecontents\PAGE}}
\output=\expandafter{\the\defaultoutput}
\newbox\headlinebox
\newbox\footlinebox
% When outputting the double column layout for indices, an output routine
% is run several times, hiding the original value of \topmark. Hence, save
% \topmark at the beginning.
%
\newtoks\savedtopmark
\newif\iftopmarksaved
\topmarksavedtrue
\def\savetopmark{%
\iftopmarksaved\else
\global\savedtopmark=\expandafter{\topmark}%
\global\topmarksavedtrue
\fi
}
% \onepageout takes a vbox as an argument.
% \shipout a vbox for a single page, adding an optional header, footer
% and footnote. This also causes index entries for this page to be written
% to the auxiliary files.
%
\def\onepageout#1{%
\hoffset=\normaloffset
%
\ifodd\pageno \advance\hoffset by \bindingoffset
\else \advance\hoffset by -\bindingoffset\fi
%
\checkchapterpage
%
% Make the heading and footing. \makeheadline and \makefootline
% use the contents of \headline and \footline.
\def\commonheadfootline{\let\hsize=\txipagewidth \texinfochars}
\ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi
\global\setbox\headlinebox = \vbox{\commonheadfootline \makeheadline}%
\ifodd\pageno \getoddfootingmarks \else \getevenfootingmarks \fi
\global\setbox\footlinebox = \vbox{\commonheadfootline \makefootline}%
%
{%
% Set context for writing to auxiliary files like index files.
% Have to do this stuff outside the \shipout because we want it to
% take effect in \write's, yet the group defined by the \vbox ends
% before the \shipout runs.
%
\atdummies % don't expand commands in the output.
\turnoffactive
\shipout\vbox{%
% Do this early so pdf references go to the beginning of the page.
\ifpdfmakepagedest \pdfdest name{\the\pageno} xyz\fi
%
\unvbox\headlinebox
\pagebody{#1}%
\ifdim\ht\footlinebox > 0pt
% Only leave this space if the footline is nonempty.
% (We lessened \vsize for it in \oddfootingyyy.)
% The \baselineskip=24pt in plain's \makefootline has no effect.
\vskip 24pt
\unvbox\footlinebox
\fi
%
}%
}%
\global\topmarksavedfalse
\advancepageno
\ifnum\outputpenalty>-20000 \else\dosupereject\fi
}
\newinsert\margin \dimen\margin=\maxdimen
% Main part of page, including any footnotes
\def\pagebody#1{\vbox to\txipageheight{\boxmaxdepth=\maxdepth #1}}
{\catcode`\@ =11
\gdef\pagecontents#1{\ifvoid\topins\else\unvbox\topins\fi
% marginal hacks, juha@viisa.uucp (Juha Takala)
\ifvoid\margin\else % marginal info is present
\rlap{\kern\hsize\vbox to\z@{\kern1pt\box\margin \vss}}\fi
\dimen@=\dp#1\relax \unvbox#1\relax
\ifvoid\footins\else\vskip\skip\footins\footnoterule \unvbox\footins\fi
\ifr@ggedbottom \kern-\dimen@ \vfil \fi}
}
% Check if we are on the first page of a chapter. Used for printing headings.
\newif\ifchapterpage
\def\checkchapterpage{%
% Get the chapter that was current at the end of the last page
\ifcase1\the\savedtopmark\fi
\let\prevchaptername\thischaptername
%
\ifodd\pageno \getoddheadingmarks \else \getevenheadingmarks \fi
\let\curchaptername\thischaptername
%
\ifx\curchaptername\prevchaptername
\chapterpagefalse
\else
\chapterpagetrue
\fi
}
% Argument parsing
% Parse an argument, then pass it to #1. The argument is the rest of
% the input line (except we remove a trailing comment). #1 should be a
% macro which expects an ordinary undelimited TeX argument.
% For example, \def\foo{\parsearg\fooxxx}.
%
\def\parsearg{\parseargusing{}}
\def\parseargusing#1#2{%
\def\argtorun{#2}%
\begingroup
\obeylines
\spaceisspace
#1%
\parseargline\empty% Insert the \empty token, see \finishparsearg below.
}
{\obeylines %
\gdef\parseargline#1^^M{%
\endgroup % End of the group started in \parsearg.
\argremovecomment #1\comment\ArgTerm%
}%
}
% First remove any @comment, then any @c comment. Pass the result on to
% \argremovespace.
\def\argremovecomment#1\comment#2\ArgTerm{\argremovec #1\c\ArgTerm}
\def\argremovec#1\c#2\ArgTerm{\argremovespace#1$ $\ArgTerm}
% \argremovec might leave us with trailing space, though; e.g.,
% @end itemize @c foo
% Note that the argument cannot contain the TeX $, as its catcode is
% changed to \other when Texinfo source is read.
\def\argremovespace#1 $#2\ArgTerm{\finishparsearg#1$\ArgTerm}
% If a _delimited_ argument is enclosed in braces, they get stripped; so
% to get _exactly_ the rest of the line, we had to prevent such situation.
% We prepended an \empty token at the very beginning and we expand it
% just before passing the control to \next.
% (But first, we have to remove the remaining $ or two.)
\def\finishparsearg#1$#2\ArgTerm{\expandafter\argtorun\expandafter{#1}}
% \parseargdef - define a command taking an argument on the line
%
% \parseargdef\foo{...}
% is roughly equivalent to
% \def\foo{\parsearg\Xfoo}
% \def\Xfoo#1{...}
\def\parseargdef#1{%
\expandafter \doparseargdef \csname\string#1\endcsname #1%
}
\def\doparseargdef#1#2{%
\def#2{\parsearg#1}%
\def#1##1%
}
% Several utility definitions with active space:
{
\obeyspaces
\gdef\obeyedspace{ }
% Make each space character in the input produce a normal interword
% space in the output. Don't allow a line break at this space, as this
% is used only in environments like @example, where each line of input
% should produce a line of output anyway.
%
\gdef\sepspaces{\obeyspaces\let =\tie}
% If an index command is used in an @example environment, any spaces
% therein should become regular spaces in the raw index file, not the
% expansion of \tie (\leavevmode \penalty \@M \ ).
\gdef\unsepspaces{\let =\space}
}
\def\flushcr{\ifx\par\lisppar \def\next##1{}\else \let\next=\relax \fi \next}
% Define the framework for environments in texinfo.tex. It's used like this:
%
% \envdef\foo{...}
% \def\Efoo{...}
%
% It's the responsibility of \envdef to insert \begingroup before the
% actual body; @end closes the group after calling \Efoo. \envdef also
% defines \thisenv, so the current environment is known; @end checks
% whether the environment name matches. The \checkenv macro can also be
% used to check whether the current environment is the one expected.
%
% Non-false conditionals (@iftex, @ifset) don't fit into this, so they
% are not treated as environments; they don't open a group. (The
% implementation of @end takes care not to call \endgroup in this
% special case.)
% At run-time, environments start with this:
\def\startenvironment#1{\begingroup\def\thisenv{#1}}
% initialize
\let\thisenv\empty
% ... but they get defined via ``\envdef\foo{...}'':
\long\def\envdef#1#2{\def#1{\startenvironment#1#2}}
\long\def\envparseargdef#1#2{\parseargdef#1{\startenvironment#1#2}}
% Check whether we're in the right environment:
\def\checkenv#1{%
\def\temp{#1}%
\ifx\thisenv\temp
\else
\badenverr
\fi
}
% Environment mismatch, #1 expected:
\def\badenverr{%
\errhelp = \EMsimple
\errmessage{This command can appear only \inenvironment\temp,
not \inenvironment\thisenv}%
}
\def\inenvironment#1{%
\ifx#1\empty
outside of any environment%
\else
in environment \expandafter\string#1%
\fi
}
% @end foo calls \checkenv and executes the definition of \Efoo.
\parseargdef\end{%
\if 1\csname iscond.#1\endcsname
\else
% The general wording of \badenverr may not be ideal.
\expandafter\checkenv\csname#1\endcsname
\csname E#1\endcsname
\endgroup
\fi
}
\newhelp\EMsimple{Press RETURN to continue.}
% Be sure we're in horizontal mode when doing a tie, since we make space
% equivalent to this in @example-like environments. Otherwise, a space
% at the beginning of a line will start with \penalty -- and
% since \penalty is valid in vertical mode, we'd end up putting the
% penalty on the vertical list instead of in the new paragraph.
{\catcode`@ = 11
% Avoid using \@M directly, because that causes trouble
% if the definition is written into an index file.
\global\let\tiepenalty = \@M
\gdef\tie{\leavevmode\penalty\tiepenalty\ }
}
% @: forces normal size whitespace following.
\def\:{\spacefactor=1000 }
% @* forces a line break.
\def\*{\unskip\hfil\break\hbox{}\ignorespaces}
% @/ allows a line break.
\let\/=\allowbreak
% @- allows explicit insertion of hyphenation points
\def\-{\discretionary{\normaldash}{}{}}%
% @. is an end-of-sentence period.
\def\.{.\spacefactor=\endofsentencespacefactor\space}
% @! is an end-of-sentence bang.
\def\!{!\spacefactor=\endofsentencespacefactor\space}
% @? is an end-of-sentence query.
\def\?{?\spacefactor=\endofsentencespacefactor\space}
% @w prevents a word break. Without the \leavevmode, @w at the
% beginning of a paragraph, when TeX is still in vertical mode, would
% produce a whole line of output instead of starting the paragraph.
\def\w#1{\leavevmode\hbox{#1}}
% @group ... @end group forces ... to be all on one page, by enclosing
% it in a TeX vbox. We use \vtop instead of \vbox to construct the box
% to keep its height that of a normal line. According to the rules for
% \topskip (p.114 of the TeXbook), the glue inserted is
% max (\topskip - \ht (first item), 0). If that height is large,
% therefore, no glue is inserted, and the space between the headline and
% the text is small, which looks bad.
%
% Another complication is that the group might be very large. This can
% cause the glue on the previous page to be unduly stretched, because it
% does not have much material. In this case, it's better to add an
% explicit \vfill so that the extra space is at the bottom. The
% threshold for doing this is if the group is more than \vfilllimit
% percent of a page (\vfilllimit can be changed inside of @tex).
%
\newbox\groupbox
\def\vfilllimit{0.7}
%
\envdef\group{%
\ifnum\catcode`\^^M=\active \else
\errhelp = \groupinvalidhelp
\errmessage{@group invalid in context where filling is enabled}%
\fi
\startsavinginserts
%
\setbox\groupbox = \vtop\bgroup
% Do @comment since we are called inside an environment such as
% @example, where each end-of-line in the input causes an
% end-of-line in the output. We don't want the end-of-line after
% the `@group' to put extra space in the output. Since @group
% should appear on a line by itself (according to the Texinfo
% manual), we don't worry about eating any user text.
\comment
}
%
% The \vtop produces a box with normal height and large depth; thus, TeX puts
% \baselineskip glue before it, and (when the next line of text is done)
% \lineskip glue after it. Thus, space below is not quite equal to space
% above. But it's pretty close.
\def\Egroup{%
% To get correct interline space between the last line of the group
% and the first line afterwards, we have to propagate \prevdepth.
\endgraf % Not \par, as it may have been set to \lisppar.
\global\dimen1 = \prevdepth
\egroup % End the \vtop.
\addgroupbox
\prevdepth = \dimen1
\checkinserts
}
\def\addgroupbox{
% \dimen0 is the vertical size of the group's box.
\dimen0 = \ht\groupbox \advance\dimen0 by \dp\groupbox
% \dimen2 is how much space is left on the page (more or less).
\dimen2 = \txipageheight \advance\dimen2 by -\pagetotal
% if the group doesn't fit on the current page, and it's a big big
% group, force a page break.
\ifdim \dimen0 > \dimen2
\ifdim \pagetotal < \vfilllimit\txipageheight
\page
\fi
\fi
\box\groupbox
}
%
% TeX puts in an \escapechar (i.e., `@') at the beginning of the help
% message, so this ends up printing `@group can only ...'.
%
\newhelp\groupinvalidhelp{%
group can only be used in environments such as @example,^^J%
where each line of input produces a line of output.}
% @need space-in-mils
% forces a page break if there is not space-in-mils remaining.
\newdimen\mil \mil=0.001in
\parseargdef\need{%
% Ensure vertical mode, so we don't make a big box in the middle of a
% paragraph.
\par
%
% If the @need value is less than one line space, it's useless.
\dimen0 = #1\mil
\dimen2 = \ht\strutbox
\advance\dimen2 by \dp\strutbox
\ifdim\dimen0 > \dimen2
% This is similar to the 'needspace' module in LaTeX.
% The first penalty allows a break if the end of the page is
% not too far away. Following penalties and skips are discarded.
% Otherwise, require at least \dimen0 of vertical space.
%
% (We used to use a \vtop to reserve space, but this had spacing issues
% when followed by a section heading, as it was not a "discardable item".
% This also has the benefit of providing glue before the page break if
% there isn't enough space.)
\vskip0pt plus \dimen0
\penalty-100
\vskip0pt plus -\dimen0
\vskip \dimen0
\penalty9999
\vskip -\dimen0
\penalty0\relax % this hides the above glue from \safewhatsit and \dobreak
\fi
}
% @br forces paragraph break (and is undocumented).
\let\br = \par
% @page forces the start of a new page.
%
\def\page{\par\vfill\supereject}
% @exdent text....
% outputs text on separate line in roman font, starting at standard page margin
% This records the amount of indent in the innermost environment.
% That's how much \exdent should take out.
\newskip\exdentamount
% This defn is used inside fill environments such as @defun.
\parseargdef\exdent{\hfil\break\hbox{\kern -\exdentamount{\rm#1}}\hfil\break}
% This defn is used inside nofill environments such as @example.
\parseargdef\nofillexdent{{\advance \leftskip by -\exdentamount
\leftline{\hskip\leftskip{\rm#1}}}}
% @inmargin{WHICH}{TEXT} puts TEXT in the WHICH margin next to the current
% paragraph. For more general purposes, use the \margin insertion
% class. WHICH is `l' or `r'. Not documented, written for gawk manual.
%
\newskip\inmarginspacing \inmarginspacing=1cm
\def\strutdepth{\dp\strutbox}
%
\def\doinmargin#1#2{\strut\vadjust{%
\nobreak
\kern-\strutdepth
\vtop to \strutdepth{%
\baselineskip=\strutdepth
\vss
% if you have multiple lines of stuff to put here, you'll need to
% make the vbox yourself of the appropriate size.
\ifx#1l%
\llap{\ignorespaces #2\hskip\inmarginspacing}%
\else
\rlap{\hskip\hsize \hskip\inmarginspacing \ignorespaces #2}%
\fi
\null
}%
}}
\def\inleftmargin{\doinmargin l}
\def\inrightmargin{\doinmargin r}
%
% @inmargin{TEXT [, RIGHT-TEXT]}
% (if RIGHT-TEXT is given, use TEXT for left page, RIGHT-TEXT for right;
% else use TEXT for both).
%
\def\inmargin#1{\parseinmargin #1,,\finish}
\def\parseinmargin#1,#2,#3\finish{% not perfect, but better than nothing.
\setbox0 = \hbox{\ignorespaces #2}%
\ifdim\wd0 > 0pt
\def\lefttext{#1}% have both texts
\def\righttext{#2}%
\else
\def\lefttext{#1}% have only one text
\def\righttext{#1}%
\fi
%
\ifodd\pageno
\def\temp{\inrightmargin\righttext}% odd page -> outside is right margin
\else
\def\temp{\inleftmargin\lefttext}%
\fi
\temp
}
% @include FILE -- \input text of FILE.
%
\def\include{\parseargusing\filenamecatcodes\includezzz}
\def\includezzz#1{%
\pushthisfilestack
\def\thisfile{#1}%
{%
\makevalueexpandable % we want to expand any @value in FILE.
\turnoffactive % and allow special characters in the expansion
\indexnofonts % Allow `@@' and other weird things in file names.
\wlog{texinfo.tex: doing @include of #1^^J}%
\edef\temp{\noexpand\input #1 }%
%
% This trickery is to read FILE outside of a group, in case it makes
% definitions, etc.
\expandafter
}\temp
\popthisfilestack
}
\def\filenamecatcodes{%
\catcode`\\=\other
\catcode`~=\other
\catcode`^=\other
\catcode`_=\other
\catcode`|=\other
\catcode`<=\other
\catcode`>=\other
\catcode`+=\other
\catcode`-=\other
\catcode`\`=\other
\catcode`\'=\other
}
\def\pushthisfilestack{%
\expandafter\pushthisfilestackX\popthisfilestack\StackTerm
}
\def\pushthisfilestackX{%
\expandafter\pushthisfilestackY\thisfile\StackTerm
}
\def\pushthisfilestackY #1\StackTerm #2\StackTerm {%
\gdef\popthisfilestack{\gdef\thisfile{#1}\gdef\popthisfilestack{#2}}%
}
\def\popthisfilestack{\errthisfilestackempty}
\def\errthisfilestackempty{\errmessage{Internal error:
the stack of filenames is empty.}}
%
\def\thisfile{}
% @center line
% outputs that line, centered.
%
\parseargdef\center{%
\ifhmode
\let\centersub\centerH
\else
\let\centersub\centerV
\fi
\centersub{\hfil \ignorespaces#1\unskip \hfil}%
\let\centersub\relax % don't let the definition persist, just in case
}
\def\centerH#1{{%
\hfil\break
\advance\hsize by -\leftskip
\advance\hsize by -\rightskip
\line{#1}%
\break
}}
%
\newcount\centerpenalty
\def\centerV#1{%
% The idea here is the same as in \startdefun, \cartouche, etc.: if
% @center is the first thing after a section heading, we need to wipe
% out the negative parskip inserted by \sectionheading, but still
% prevent a page break here.
\centerpenalty = \lastpenalty
\ifnum\centerpenalty>10000 \vskip\parskip \fi
\ifnum\centerpenalty>9999 \penalty\centerpenalty \fi
\line{\kern\leftskip #1\kern\rightskip}%
}
% @sp n outputs n lines of vertical space
%
\parseargdef\sp{\vskip #1\baselineskip}
% @comment ...line which is ignored...
% @c is the same as @comment
% @ignore ... @end ignore is another way to write a comment
\def\c{\begingroup \catcode`\^^M=\active%
\catcode`\@=\other \catcode`\{=\other \catcode`\}=\other%
\cxxx}
{\catcode`\^^M=\active \gdef\cxxx#1^^M{\endgroup}}
%
\let\comment\c
% @paragraphindent NCHARS
% We'll use ems for NCHARS, close enough.
% NCHARS can also be the word `asis' or `none'.
% We cannot feasibly implement @paragraphindent asis, though.
%
\def\asisword{asis} % no translation, these are keywords
\def\noneword{none}
%
\parseargdef\paragraphindent{%
\def\temp{#1}%
\ifx\temp\asisword
\else
\ifx\temp\noneword
\defaultparindent = 0pt
\else
\defaultparindent = #1em
\fi
\fi
\parindent = \defaultparindent
}
% @exampleindent NCHARS
% We'll use ems for NCHARS like @paragraphindent.
% It seems @exampleindent asis isn't necessary, but
% I preserve it to make it similar to @paragraphindent.
\parseargdef\exampleindent{%
\def\temp{#1}%
\ifx\temp\asisword
\else
\ifx\temp\noneword
\lispnarrowing = 0pt
\else
\lispnarrowing = #1em
\fi
\fi
}
% @firstparagraphindent WORD
% If WORD is `none', then suppress indentation of the first paragraph
% after a section heading. If WORD is `insert', then do indent at such
% paragraphs.
%
% The paragraph indentation is suppressed or not by calling
% \suppressfirstparagraphindent, which the sectioning commands do.
% We switch the definition of this back and forth according to WORD.
% By default, we suppress indentation.
%
\def\suppressfirstparagraphindent{\dosuppressfirstparagraphindent}
\def\insertword{insert}
%
\parseargdef\firstparagraphindent{%
\def\temp{#1}%
\ifx\temp\noneword
\let\suppressfirstparagraphindent = \dosuppressfirstparagraphindent
\else\ifx\temp\insertword
\let\suppressfirstparagraphindent = \relax
\else
\errhelp = \EMsimple
\errmessage{Unknown @firstparagraphindent option `\temp'}%
\fi\fi
}
% Here is how we actually suppress indentation. Redefine \everypar to
% \kern backwards by \parindent, and then reset itself to empty.
%
% We also make \indent itself not actually do anything until the next
% paragraph.
%
\gdef\dosuppressfirstparagraphindent{%
\gdef\indent {\restorefirstparagraphindent \indent}%
\gdef\noindent{\restorefirstparagraphindent \noindent}%
\global\everypar = {\kern -\parindent \restorefirstparagraphindent}%
}
%
\gdef\restorefirstparagraphindent{%
\global\let\indent = \ptexindent
\global\let\noindent = \ptexnoindent
\global\everypar = {}%
}
% leave vertical mode without cancelling any first paragraph indent
\gdef\imageindent{%
\toks0=\everypar
\everypar={}%
\ptexnoindent
\global\everypar=\toks0
}
% @refill is a no-op.
\let\refill=\relax
% @setfilename INFO-FILENAME - ignored
\let\setfilename=\comment
% @bye.
\outer\def\bye{\chappager\pagelabels\tracingstats=1\ptexend}
\message{pdf,}
% adobe `portable' document format
\newcount\tempnum
\newcount\lnkcount
\newtoks\filename
\newcount\filenamelength
\newcount\pgn
\newtoks\toksA
\newtoks\toksB
\newtoks\toksC
\newtoks\toksD
\newbox\boxA
\newbox\boxB
\newcount\countA
\newif\ifpdf
\newif\ifpdfmakepagedest
%
% For LuaTeX
%
\newif\iftxiuseunicodedestname
\txiuseunicodedestnamefalse % For pdfTeX etc.
\ifx\luatexversion\thisisundefined
\else
% Use Unicode destination names
\txiuseunicodedestnametrue
% Escape PDF strings with converting UTF-16 from UTF-8
\begingroup
\catcode`\%=12
\directlua{
function UTF16oct(str)
tex.sprint(string.char(0x5c) .. '376' .. string.char(0x5c) .. '377')
for c in string.utfvalues(str) do
if c < 0x10000 then
tex.sprint(
string.format(string.char(0x5c) .. string.char(0x25) .. '03o' ..
string.char(0x5c) .. string.char(0x25) .. '03o',
math.floor(c / 256), math.floor(c % 256)))
else
c = c - 0x10000
local c_hi = c / 1024 + 0xd800
local c_lo = c % 1024 + 0xdc00
tex.sprint(
string.format(string.char(0x5c) .. string.char(0x25) .. '03o' ..
string.char(0x5c) .. string.char(0x25) .. '03o' ..
string.char(0x5c) .. string.char(0x25) .. '03o' ..
string.char(0x5c) .. string.char(0x25) .. '03o',
math.floor(c_hi / 256), math.floor(c_hi % 256),
math.floor(c_lo / 256), math.floor(c_lo % 256)))
end
end
end
}
\endgroup
\def\pdfescapestrutfsixteen#1{\directlua{UTF16oct('\luaescapestring{#1}')}}
% Escape PDF strings without converting
\begingroup
\directlua{
function PDFescstr(str)
for c in string.bytes(str) do
if c <= 0x20 or c >= 0x80 or c == 0x28 or c == 0x29 or c == 0x5c then
tex.sprint(-2,
string.format(string.char(0x5c) .. string.char(0x25) .. '03o',
c))
else
tex.sprint(-2, string.char(c))
end
end
end
}
% The -2 in the arguments here gives all the input to TeX catcode 12
% (other) or 10 (space), preventing undefined control sequence errors. See
% https://lists.gnu.org/archive/html/bug-texinfo/2019-08/msg00031.html
%
\endgroup
\def\pdfescapestring#1{\directlua{PDFescstr('\luaescapestring{#1}')}}
\ifnum\luatexversion>84
% For LuaTeX >= 0.85
\def\pdfdest{\pdfextension dest}
\let\pdfoutput\outputmode
\def\pdfliteral{\pdfextension literal}
\def\pdfcatalog{\pdfextension catalog}
\def\pdftexversion{\numexpr\pdffeedback version\relax}
\let\pdfximage\saveimageresource
\let\pdfrefximage\useimageresource
\let\pdflastximage\lastsavedimageresourceindex
\def\pdfendlink{\pdfextension endlink\relax}
\def\pdfoutline{\pdfextension outline}
\def\pdfstartlink{\pdfextension startlink}
\def\pdffontattr{\pdfextension fontattr}
\def\pdfobj{\pdfextension obj}
\def\pdflastobj{\numexpr\pdffeedback lastobj\relax}
\let\pdfpagewidth\pagewidth
\let\pdfpageheight\pageheight
\edef\pdfhorigin{\pdfvariable horigin}
\edef\pdfvorigin{\pdfvariable vorigin}
\fi
\fi
% when pdftex is run in dvi mode, \pdfoutput is defined (so \pdfoutput=1
% can be set). So we test for \relax and 0 as well as being undefined.
\ifx\pdfoutput\thisisundefined
\else
\ifx\pdfoutput\relax
\else
\ifcase\pdfoutput
\else
\pdftrue
\fi
\fi
\fi
\newif\ifpdforxetex
\pdforxetexfalse
\ifpdf
\pdforxetextrue
\fi
\ifx\XeTeXrevision\thisisundefined\else
\pdforxetextrue
\fi
% Output page labels information.
% See PDF reference v.1.7 p.594, section 8.3.1.
% Page label ranges must be increasing.
\ifpdf
\def\pagelabels{%
\def\title{0 << /P (T-) /S /D >>}%
%
% support @contents at very end of document
\ifnum\contentsendcount=\pagecount
\ifnum\arabiccount<\romancount
\pdfcatalog{/PageLabels << /Nums
[\title
\the\arabiccount << /S /D >>
\the\romancount << /S /r >>
] >> }\relax
\fi
% no contents in document
\else\ifnum\contentsendcount=0
\pdfcatalog{/PageLabels << /Nums
[\title
\the\arabiccount << /S /D >>
] >> }\relax
\else
\pdfcatalog{/PageLabels << /Nums
[\title
\the\romancount << /S /r >>
\the\contentsendcount << /S /D >>
] >> }\relax
\fi\fi
}
\else
\let\pagelabels\relax
\fi
\newcount\pagecount \pagecount=0
\newcount\romancount \romancount=0
\newcount\arabiccount \arabiccount=0
\newcount\contentsendcount \contentsendcount=0
\ifpdf
\let\ptxadvancepageno\advancepageno
\def\advancepageno{%
\ptxadvancepageno\global\advance\pagecount by 1
}
\fi
% PDF uses PostScript string constants for the names of xref targets,
% for display in the outlines, and in other places. Thus, we have to
% double any backslashes. Otherwise, a name like "\node" will be
% interpreted as a newline (\n), followed by o, d, e. Not good.
%
% See http://www.ntg.nl/pipermail/ntg-pdftex/2004-July/000654.html and
% related messages. The final outcome is that it is up to the TeX user
% to double the backslashes and otherwise make the string valid, so
% that's what we do. pdftex 1.30.0 (ca.2005) introduced a primitive to
% do this reliably, so we use it.
% #1 is a control sequence in which to do the replacements,
% which we \xdef.
\def\txiescapepdf#1{%
\ifx\pdfescapestring\thisisundefined
% No primitive available; should we give a warning or log?
% Many times it won't matter.
\xdef#1{#1}%
\else
% The expandable \pdfescapestring primitive escapes parentheses,
% backslashes, and other special chars.
\xdef#1{\pdfescapestring{#1}}%
\fi
}
\def\txiescapepdfutfsixteen#1{%
\ifx\pdfescapestrutfsixteen\thisisundefined
% No UTF-16 converting macro available.
\txiescapepdf{#1}%
\else
\xdef#1{\pdfescapestrutfsixteen{#1}}%
\fi
}
\newhelp\nopdfimagehelp{Texinfo supports .png, .jpg, .jpeg, and .pdf images
with PDF output, and none of those formats could be found. (.eps cannot
be supported due to the design of the PDF format; use regular TeX (DVI
output) for that.)}
\ifpdf
%
% Color manipulation macros using ideas from pdfcolor.tex,
% except using rgb instead of cmyk; the latter is said to render as a
% very dark gray on-screen and a very dark halftone in print, instead
% of actual black. The dark red here is dark enough to print on paper as
% nearly black, but still distinguishable for online viewing. We use
% black by default, though.
\def\rgbDarkRed{0.50 0.09 0.12}
\def\rgbBlack{0 0 0}
%
% rg sets the color for filling (usual text, etc.);
% RG sets the color for stroking (thin rules, e.g., normal _'s).
\def\pdfsetcolor#1{\pdfliteral{#1 rg #1 RG}}
%
% Set color, and create a mark which defines \thiscolor accordingly,
% so that \makeheadline knows which color to restore.
\def\curcolor{0 0 0}%
\def\setcolor#1{%
\ifx#1\curcolor\else
\xdef\currentcolordefs{\gdef\noexpand\thiscolor{#1}}%
\domark
\pdfsetcolor{#1}%
\xdef\curcolor{#1}%
\fi
}
%
\let\maincolor\rgbBlack
\pdfsetcolor{\maincolor}
\edef\thiscolor{\maincolor}
\def\currentcolordefs{}
%
\def\makefootline{%
\baselineskip24pt
\line{\pdfsetcolor{\maincolor}\the\footline}%
}
%
\def\makeheadline{%
\vbox to 0pt{%
\vskip-22.5pt
\line{%
\vbox to8.5pt{}%
% Extract \thiscolor definition from the marks.
\getcolormarks
% Typeset the headline with \maincolor, then restore the color.
\pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}%
}%
\vss
}%
\nointerlineskip
}
%
%
\pdfcatalog{/PageMode /UseOutlines}
%
% #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto).
\def\dopdfimage#1#2#3{%
\def\pdfimagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}%
\def\pdfimageheight{#3}\setbox2 = \hbox{\ignorespaces #3}%
%
% pdftex (and the PDF format) support .pdf, .png, .jpg (among
% others). Let's try in that order, PDF first since if
% someone has a scalable image, presumably better to use that than a
% bitmap.
\let\pdfimgext=\empty
\begingroup
\openin 1 #1.pdf \ifeof 1
\openin 1 #1.PDF \ifeof 1
\openin 1 #1.png \ifeof 1
\openin 1 #1.jpg \ifeof 1
\openin 1 #1.jpeg \ifeof 1
\openin 1 #1.JPG \ifeof 1
\errhelp = \nopdfimagehelp
\errmessage{Could not find image file #1 for pdf}%
\else \gdef\pdfimgext{JPG}%
\fi
\else \gdef\pdfimgext{jpeg}%
\fi
\else \gdef\pdfimgext{jpg}%
\fi
\else \gdef\pdfimgext{png}%
\fi
\else \gdef\pdfimgext{PDF}%
\fi
\else \gdef\pdfimgext{pdf}%
\fi
\closein 1
\endgroup
%
% without \immediate, ancient pdftex seg faults when the same image is
% included twice. (Version 3.14159-pre-1.0-unofficial-20010704.)
\ifnum\pdftexversion < 14
\immediate\pdfimage
\else
\immediate\pdfximage
\fi
\ifdim \wd0 >0pt width \pdfimagewidth \fi
\ifdim \wd2 >0pt height \pdfimageheight \fi
\ifnum\pdftexversion<13
#1.\pdfimgext
\else
{#1.\pdfimgext}%
\fi
\ifnum\pdftexversion < 14 \else
\pdfrefximage \pdflastximage
\fi}
%
\def\setpdfdestname#1{{%
% We have to set dummies so commands such as @code, and characters
% such as \, aren't expanded when present in a section title.
\indexnofonts
\makevalueexpandable
\turnoffactive
\iftxiuseunicodedestname
\ifx \declaredencoding \latone
% Pass through Latin-1 characters.
% LuaTeX with byte wise I/O converts Latin-1 characters to Unicode.
\else
\ifx \declaredencoding \utfeight
% Pass through Unicode characters.
\else
% Use ASCII approximations in destination names.
\passthroughcharsfalse
\fi
\fi
\else
% Use ASCII approximations in destination names.
\passthroughcharsfalse
\fi
\def\pdfdestname{#1}%
\txiescapepdf\pdfdestname
}}
%
\def\setpdfoutlinetext#1{{%
\indexnofonts
\makevalueexpandable
\turnoffactive
\ifx \declaredencoding \latone
% The PDF format can use an extended form of Latin-1 in bookmark
% strings. See Appendix D of the PDF Reference, Sixth Edition, for
% the "PDFDocEncoding".
\passthroughcharstrue
% Pass through Latin-1 characters.
% LuaTeX: Convert to Unicode
% pdfTeX: Use Latin-1 as PDFDocEncoding
\def\pdfoutlinetext{#1}%
\else
\ifx \declaredencoding \utfeight
\ifx\luatexversion\thisisundefined
% For pdfTeX with UTF-8.
% TODO: the PDF format can use UTF-16 in bookmark strings,
% but the code for this isn't done yet.
% Use ASCII approximations.
\passthroughcharsfalse
\def\pdfoutlinetext{#1}%
\else
% For LuaTeX with UTF-8.
% Pass through Unicode characters for title texts.
\passthroughcharstrue
\def\pdfoutlinetext{#1}%
\fi
\else
% For non-Latin-1 or non-UTF-8 encodings.
% Use ASCII approximations.
\passthroughcharsfalse
\def\pdfoutlinetext{#1}%
\fi
\fi
% LuaTeX: Convert to UTF-16
% pdfTeX: Use Latin-1 as PDFDocEncoding
\txiescapepdfutfsixteen\pdfoutlinetext
}}
%
\def\pdfmkdest#1{%
\setpdfdestname{#1}%
\safewhatsit{\pdfdest name{\pdfdestname} xyz}%
}
%
% used to mark target names; must be expandable.
\def\pdfmkpgn#1{#1}
%
% by default, use black for everything.
\def\urlcolor{\rgbBlack}
\let\linkcolor\rgbBlack
\def\endlink{\setcolor{\maincolor}\pdfendlink}
%
% Adding outlines to PDF; macros for calculating structure of outlines
% come from Petr Olsak
\def\expnumber#1{\expandafter\ifx\csname#1\endcsname\relax 0%
\else \csname#1\endcsname \fi}
\def\advancenumber#1{\tempnum=\expnumber{#1}\relax
\advance\tempnum by 1
\expandafter\xdef\csname#1\endcsname{\the\tempnum}}
%
% #1 is the section text, which is what will be displayed in the
% outline by the pdf viewer. #2 is the pdf expression for the number
% of subentries (or empty, for subsubsections). #3 is the node text,
% which might be empty if this toc entry had no corresponding node.
% #4 is the page number
%
\def\dopdfoutline#1#2#3#4{%
% Generate a link to the node text if that exists; else, use the
% page number. We could generate a destination for the section
% text in the case where a section has no node, but it doesn't
% seem worth the trouble, since most documents are normally structured.
\setpdfoutlinetext{#1}
\setpdfdestname{#3}
\ifx\pdfdestname\empty
\def\pdfdestname{#4}%
\fi
%
\pdfoutline goto name{\pdfmkpgn{\pdfdestname}}#2{\pdfoutlinetext}%
}
%
\def\pdfmakeoutlines{%
\begingroup
% Read toc silently, to get counts of subentries for \pdfoutline.
\def\partentry##1##2##3##4{}% ignore parts in the outlines
\def\numchapentry##1##2##3##4{%
\def\thischapnum{##2}%
\def\thissecnum{0}%
\def\thissubsecnum{0}%
}%
\def\numsecentry##1##2##3##4{%
\advancenumber{chap\thischapnum}%
\def\thissecnum{##2}%
\def\thissubsecnum{0}%
}%
\def\numsubsecentry##1##2##3##4{%
\advancenumber{sec\thissecnum}%
\def\thissubsecnum{##2}%
}%
\def\numsubsubsecentry##1##2##3##4{%
\advancenumber{subsec\thissubsecnum}%
}%
\def\thischapnum{0}%
\def\thissecnum{0}%
\def\thissubsecnum{0}%
%
% use \def rather than \let here because we redefine \chapentry et
% al. a second time, below.
\def\appentry{\numchapentry}%
\def\appsecentry{\numsecentry}%
\def\appsubsecentry{\numsubsecentry}%
\def\appsubsubsecentry{\numsubsubsecentry}%
\def\unnchapentry{\numchapentry}%
\def\unnsecentry{\numsecentry}%
\def\unnsubsecentry{\numsubsecentry}%
\def\unnsubsubsecentry{\numsubsubsecentry}%
\readdatafile{toc}%
%
% Read toc second time, this time actually producing the outlines.
% The `-' means take the \expnumber as the absolute number of
% subentries, which we calculated on our first read of the .toc above.
%
% We use the node names as the destinations.
%
% Currently we prefix the section name with the section number
% for chapter and appendix headings only in order to avoid too much
% horizontal space being required in the PDF viewer.
\def\numchapentry##1##2##3##4{%
\dopdfoutline{##2 ##1}{count-\expnumber{chap##2}}{##3}{##4}}%
\def\unnchapentry##1##2##3##4{%
\dopdfoutline{##1}{count-\expnumber{chap##2}}{##3}{##4}}%
\def\numsecentry##1##2##3##4{%
\dopdfoutline{##1}{count-\expnumber{sec##2}}{##3}{##4}}%
\def\numsubsecentry##1##2##3##4{%
\dopdfoutline{##1}{count-\expnumber{subsec##2}}{##3}{##4}}%
\def\numsubsubsecentry##1##2##3##4{% count is always zero
\dopdfoutline{##1}{}{##3}{##4}}%
%
% PDF outlines are displayed using system fonts, instead of
% document fonts. Therefore we cannot use special characters,
% since the encoding is unknown. For example, the eogonek from
% Latin 2 (0xea) gets translated to a | character. Info from
% Staszek Wawrykiewicz, 19 Jan 2004 04:09:24 +0100.
%
% TODO this right, we have to translate 8-bit characters to
% their "best" equivalent, based on the @documentencoding. Too
% much work for too little return. Just use the ASCII equivalents
% we use for the index sort strings.
%
\indexnofonts
\setupdatafile
% We can have normal brace characters in the PDF outlines, unlike
% Texinfo index files. So set that up.
\def\{{\lbracecharliteral}%
\def\}{\rbracecharliteral}%
\catcode`\\=\active \otherbackslash
\input \tocreadfilename
\endgroup
}
{\catcode`[=1 \catcode`]=2
\catcode`{=\other \catcode`}=\other
\gdef\lbracecharliteral[{]%
\gdef\rbracecharliteral[}]%
]
%
\def\skipspaces#1{\def\PP{#1}\def\D{|}%
\ifx\PP\D\let\nextsp\relax
\else\let\nextsp\skipspaces
\addtokens{\filename}{\PP}%
\advance\filenamelength by 1
\fi
\nextsp}
\def\getfilename#1{%
\filenamelength=0
% If we don't expand the argument now, \skipspaces will get
% snagged on things like "@value{foo}".
\edef\temp{#1}%
\expandafter\skipspaces\temp|\relax
}
\ifnum\pdftexversion < 14
\let \startlink \pdfannotlink
\else
\let \startlink \pdfstartlink
\fi
% make a live url in pdf output.
\def\pdfurl#1{%
\begingroup
% it seems we really need yet another set of dummies; have not
% tried to figure out what each command should do in the context
% of @url. for now, just make @/ a no-op, that's the only one
% people have actually reported a problem with.
%
\normalturnoffactive
\def\@{@}%
\let\/=\empty
\makevalueexpandable
% do we want to go so far as to use \indexnofonts instead of just
% special-casing \var here?
\def\var##1{##1}%
%
\leavevmode\setcolor{\urlcolor}%
\startlink attr{/Border [0 0 0]}%
user{/Subtype /Link /A << /S /URI /URI (#1) >>}%
\endgroup}
% \pdfgettoks - Surround page numbers in #1 with @pdflink. #1 may
% be a simple number, or a list of numbers in the case of an index
% entry.
\def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}}
\def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
\def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks}
\def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}}
\def\maketoks{%
\expandafter\poptoks\the\toksA|ENDTOKS|\relax
\ifx\first0\adn0
\else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3
\else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6
\else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9
\else
\ifnum0=\countA\else\makelink\fi
\ifx\first.\let\next=\done\else
\let\next=\maketoks
\addtokens{\toksB}{\the\toksD}
\ifx\first,\addtokens{\toksB}{\space}\fi
\fi
\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
\next}
\def\makelink{\addtokens{\toksB}%
{\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0}
\def\pdflink#1{\pdflinkpage{#1}{#1}}%
\def\pdflinkpage#1#2{%
\startlink attr{/Border [0 0 0]} goto name{\pdfmkpgn{#1}}
\setcolor{\linkcolor}#2\endlink}
\def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
\else
% non-pdf mode
\let\pdfmkdest = \gobble
\let\pdfurl = \gobble
\let\endlink = \relax
\let\setcolor = \gobble
\let\pdfsetcolor = \gobble
\let\pdfmakeoutlines = \relax
\fi % \ifx\pdfoutput
%
% For XeTeX
%
\ifx\XeTeXrevision\thisisundefined
\else
%
% XeTeX version check
%
\ifnum\strcmp{\the\XeTeXversion\XeTeXrevision}{0.99996}>-1
% TeX Live 2016 contains XeTeX 0.99996 and xdvipdfmx 20160307.
% It can use the `dvipdfmx:config' special (from TeX Live SVN r40941).
% For avoiding PDF destination name replacement, we use this special
% instead of xdvipdfmx's command line option `-C 0x0010'.
\special{dvipdfmx:config C 0x0010}
% XeTeX 0.99995+ comes with xdvipdfmx 20160307+.
% It can handle Unicode destination names for PDF.
\txiuseunicodedestnametrue
\else
% XeTeX < 0.99996 (TeX Live < 2016) cannot use the
% `dvipdfmx:config' special.
% So for avoiding PDF destination name replacement,
% xdvipdfmx's command line option `-C 0x0010' is necessary.
%
% XeTeX < 0.99995 can not handle Unicode destination names for PDF
% because xdvipdfmx 20150315 has a UTF-16 conversion issue.
% It is fixed by xdvipdfmx 20160106 (TeX Live SVN r39753).
\txiuseunicodedestnamefalse
\fi
%
% Color support
%
\def\rgbDarkRed{0.50 0.09 0.12}
\def\rgbBlack{0 0 0}
%
\def\pdfsetcolor#1{\special{pdf:scolor [#1]}}
%
% Set color, and create a mark which defines \thiscolor accordingly,
% so that \makeheadline knows which color to restore.
\def\setcolor#1{%
\xdef\currentcolordefs{\gdef\noexpand\thiscolor{#1}}%
\domark
\pdfsetcolor{#1}%
}
%
\def\maincolor{\rgbBlack}
\pdfsetcolor{\maincolor}
\edef\thiscolor{\maincolor}
\def\currentcolordefs{}
%
\def\makefootline{%
\baselineskip24pt
\line{\pdfsetcolor{\maincolor}\the\footline}%
}
%
\def\makeheadline{%
\vbox to 0pt{%
\vskip-22.5pt
\line{%
\vbox to8.5pt{}%
% Extract \thiscolor definition from the marks.
\getcolormarks
% Typeset the headline with \maincolor, then restore the color.
\pdfsetcolor{\maincolor}\the\headline\pdfsetcolor{\thiscolor}%
}%
\vss
}%
\nointerlineskip
}
%
% PDF outline support
%
% Emulate pdfTeX primitive
\def\pdfdest name#1 xyz{%
\special{pdf:dest (#1) [@thispage /XYZ @xpos @ypos null]}%
}
%
\def\setpdfdestname#1{{%
% We have to set dummies so commands such as @code, and characters
% such as \, aren't expanded when present in a section title.
\indexnofonts
\makevalueexpandable
\turnoffactive
\iftxiuseunicodedestname
% Pass through Unicode characters.
\else
% Use ASCII approximations in destination names.
\passthroughcharsfalse
\fi
\def\pdfdestname{#1}%
\txiescapepdf\pdfdestname
}}
%
\def\setpdfoutlinetext#1{{%
\turnoffactive
% Always use Unicode characters in title texts.
\def\pdfoutlinetext{#1}%
% For XeTeX, xdvipdfmx converts to UTF-16.
% So we do not convert.
\txiescapepdf\pdfoutlinetext
}}
%
\def\pdfmkdest#1{%
\setpdfdestname{#1}%
\safewhatsit{\pdfdest name{\pdfdestname} xyz}%
}
%
% by default, use black for everything.
\def\urlcolor{\rgbBlack}
\def\linkcolor{\rgbBlack}
\def\endlink{\setcolor{\maincolor}\pdfendlink}
%
\def\dopdfoutline#1#2#3#4{%
\setpdfoutlinetext{#1}
\setpdfdestname{#3}
\ifx\pdfdestname\empty
\def\pdfdestname{#4}%
\fi
%
\special{pdf:out [-] #2 << /Title (\pdfoutlinetext) /A
<< /S /GoTo /D (\pdfdestname) >> >> }%
}
%
\def\pdfmakeoutlines{%
\begingroup
%
% For XeTeX, counts of subentries are not necessary.
% Therefore, we read toc only once.
%
% We use node names as destinations.
%
% Currently we prefix the section name with the section number
% for chapter and appendix headings only in order to avoid too much
% horizontal space being required in the PDF viewer.
\def\partentry##1##2##3##4{}% ignore parts in the outlines
\def\numchapentry##1##2##3##4{%
\dopdfoutline{##2 ##1}{1}{##3}{##4}}%
\def\numsecentry##1##2##3##4{%
\dopdfoutline{##1}{2}{##3}{##4}}%
\def\numsubsecentry##1##2##3##4{%
\dopdfoutline{##1}{3}{##3}{##4}}%
\def\numsubsubsecentry##1##2##3##4{%
\dopdfoutline{##1}{4}{##3}{##4}}%
%
\let\appentry\numchapentry%
\let\appsecentry\numsecentry%
\let\appsubsecentry\numsubsecentry%
\let\appsubsubsecentry\numsubsubsecentry%
\def\unnchapentry##1##2##3##4{%
\dopdfoutline{##1}{1}{##3}{##4}}%
\let\unnsecentry\numsecentry%
\let\unnsubsecentry\numsubsecentry%
\let\unnsubsubsecentry\numsubsubsecentry%
%
% For XeTeX, xdvipdfmx converts strings to UTF-16.
% Therefore, the encoding and the language may not be considered.
%
\indexnofonts
\setupdatafile
% We can have normal brace characters in the PDF outlines, unlike
% Texinfo index files. So set that up.
\def\{{\lbracecharliteral}%
\def\}{\rbracecharliteral}%
\catcode`\\=\active \otherbackslash
\input \tocreadfilename
\endgroup
}
{\catcode`[=1 \catcode`]=2
\catcode`{=\other \catcode`}=\other
\gdef\lbracecharliteral[{]%
\gdef\rbracecharliteral[}]%
]
\special{pdf:docview << /PageMode /UseOutlines >> }
% ``\special{pdf:tounicode ...}'' is not necessary
% because xdvipdfmx converts strings from UTF-8 to UTF-16 without it.
% However, due to a UTF-16 conversion issue of xdvipdfmx 20150315,
% ``\special{pdf:dest ...}'' cannot handle non-ASCII strings.
% It is fixed by xdvipdfmx 20160106 (TeX Live SVN r39753).
%
\def\skipspaces#1{\def\PP{#1}\def\D{|}%
\ifx\PP\D\let\nextsp\relax
\else\let\nextsp\skipspaces
\addtokens{\filename}{\PP}%
\advance\filenamelength by 1
\fi
\nextsp}
\def\getfilename#1{%
\filenamelength=0
% If we don't expand the argument now, \skipspaces will get
% snagged on things like "@value{foo}".
\edef\temp{#1}%
\expandafter\skipspaces\temp|\relax
}
% make a live url in pdf output.
\def\pdfurl#1{%
\begingroup
% it seems we really need yet another set of dummies; have not
% tried to figure out what each command should do in the context
% of @url. for now, just make @/ a no-op, that's the only one
% people have actually reported a problem with.
%
\normalturnoffactive
\def\@{@}%
\let\/=\empty
\makevalueexpandable
% do we want to go so far as to use \indexnofonts instead of just
% special-casing \var here?
\def\var##1{##1}%
%
\leavevmode\setcolor{\urlcolor}%
\special{pdf:bann << /Border [0 0 0]
/Subtype /Link /A << /S /URI /URI (#1) >> >>}%
\endgroup}
\def\endlink{\setcolor{\maincolor}\special{pdf:eann}}
\def\pdfgettoks#1.{\setbox\boxA=\hbox{\toksA={#1.}\toksB={}\maketoks}}
\def\addtokens#1#2{\edef\addtoks{\noexpand#1={\the#1#2}}\addtoks}
\def\adn#1{\addtokens{\toksC}{#1}\global\countA=1\let\next=\maketoks}
\def\poptoks#1#2|ENDTOKS|{\let\first=#1\toksD={#1}\toksA={#2}}
\def\maketoks{%
\expandafter\poptoks\the\toksA|ENDTOKS|\relax
\ifx\first0\adn0
\else\ifx\first1\adn1 \else\ifx\first2\adn2 \else\ifx\first3\adn3
\else\ifx\first4\adn4 \else\ifx\first5\adn5 \else\ifx\first6\adn6
\else\ifx\first7\adn7 \else\ifx\first8\adn8 \else\ifx\first9\adn9
\else
\ifnum0=\countA\else\makelink\fi
\ifx\first.\let\next=\done\else
\let\next=\maketoks
\addtokens{\toksB}{\the\toksD}
\ifx\first,\addtokens{\toksB}{\space}\fi
\fi
\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi
\next}
\def\makelink{\addtokens{\toksB}%
{\noexpand\pdflink{\the\toksC}}\toksC={}\global\countA=0}
\def\pdflink#1{\pdflinkpage{#1}{#1}}%
\def\pdflinkpage#1#2{%
\special{pdf:bann << /Border [0 0 0]
/Type /Annot /Subtype /Link /A << /S /GoTo /D (#1) >> >>}%
\setcolor{\linkcolor}#2\endlink}
\def\done{\edef\st{\global\noexpand\toksA={\the\toksB}}\st}
%
%
% @image support
%
% #1 is image name, #2 width (might be empty/whitespace), #3 height (ditto).
\def\doxeteximage#1#2#3{%
\def\xeteximagewidth{#2}\setbox0 = \hbox{\ignorespaces #2}%
\def\xeteximageheight{#3}\setbox2 = \hbox{\ignorespaces #3}%
%
% XeTeX (and the PDF format) supports .pdf, .png, .jpg (among
% others). Let's try in that order, PDF first since if
% someone has a scalable image, presumably better to use that than a
% bitmap.
\let\xeteximgext=\empty
\begingroup
\openin 1 #1.pdf \ifeof 1
\openin 1 #1.PDF \ifeof 1
\openin 1 #1.png \ifeof 1
\openin 1 #1.jpg \ifeof 1
\openin 1 #1.jpeg \ifeof 1
\openin 1 #1.JPG \ifeof 1
\errmessage{Could not find image file #1 for XeTeX}%
\else \gdef\xeteximgext{JPG}%
\fi
\else \gdef\xeteximgext{jpeg}%
\fi
\else \gdef\xeteximgext{jpg}%
\fi
\else \gdef\xeteximgext{png}%
\fi
\else \gdef\xeteximgext{PDF}%
\fi
\else \gdef\xeteximgext{pdf}%
\fi
\closein 1
\endgroup
%
% Putting an \hbox around the image can prevent an over-long line
% after the image.
\hbox\bgroup
\def\xetexpdfext{pdf}%
\ifx\xeteximgext\xetexpdfext
\XeTeXpdffile "#1".\xeteximgext ""
\else
\def\xetexpdfext{PDF}%
\ifx\xeteximgext\xetexpdfext
\XeTeXpdffile "#1".\xeteximgext ""
\else
\XeTeXpicfile "#1".\xeteximgext ""
\fi
\fi
\ifdim \wd0 >0pt width \xeteximagewidth \fi
\ifdim \wd2 >0pt height \xeteximageheight \fi \relax
\egroup
}
\fi
%
\message{fonts,}
% Set the baselineskip to #1, and the lineskip and strut size
% correspondingly. There is no deep meaning behind these magic numbers
% used as factors; they just match (closely enough) what Knuth defined.
%
\def\lineskipfactor{.08333}
\def\strutheightpercent{.70833}
\def\strutdepthpercent {.29167}
%
% can get a sort of poor man's double spacing by redefining this.
\def\baselinefactor{1}
%
\newdimen\textleading
\def\setleading#1{%
\dimen0 = #1\relax
\normalbaselineskip = \baselinefactor\dimen0
\normallineskip = \lineskipfactor\normalbaselineskip
\normalbaselines
\setbox\strutbox =\hbox{%
\vrule width0pt height\strutheightpercent\baselineskip
depth \strutdepthpercent \baselineskip
}%
}
% PDF CMaps. See also LaTeX's t1.cmap.
%
% do nothing with this by default.
\expandafter\let\csname cmapOT1\endcsname\gobble
\expandafter\let\csname cmapOT1IT\endcsname\gobble
\expandafter\let\csname cmapOT1TT\endcsname\gobble
% if we are producing pdf, and we have \pdffontattr, then define cmaps.
% (\pdffontattr was introduced many years ago, but people still run
% older pdftex's; it's easy to conditionalize, so we do.)
\ifpdf \ifx\pdffontattr\thisisundefined \else
\begingroup
\catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
\catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeX-OT1-0)
%%Title: (TeX-OT1-0 TeX OT1 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeX)
/Ordering (OT1)
/Supplement 0
>> def
/CMapName /TeX-OT1-0 def
/CMapType 2 def
1 begincodespacerange
<00> <7F>
endcodespacerange
8 beginbfrange
<00> <01> <0393>
<09> <0A> <03A8>
<23> <26> <0023>
<28> <3B> <0028>
<3F> <5B> <003F>
<5D> <5E> <005D>
<61> <7A> <0061>
<7B> <7C> <2013>
endbfrange
40 beginbfchar
<02> <0398>
<03> <039B>
<04> <039E>
<05> <03A0>
<06> <03A3>
<07> <03D2>
<08> <03A6>
<0B> <00660066>
<0C> <00660069>
<0D> <0066006C>
<0E> <006600660069>
<0F> <00660066006C>
<10> <0131>
<11> <0237>
<12> <0060>
<13> <00B4>
<14> <02C7>
<15> <02D8>
<16> <00AF>
<17> <02DA>
<18> <00B8>
<19> <00DF>
<1A> <00E6>
<1B> <0153>
<1C> <00F8>
<1D> <00C6>
<1E> <0152>
<1F> <00D8>
<21> <0021>
<22> <201D>
<27> <2019>
<3C> <00A1>
<3D> <003D>
<3E> <00BF>
<5C> <201C>
<5F> <02D9>
<60> <2018>
<7D> <02DD>
<7E> <007E>
<7F> <00A8>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
%%EndResource
%%EOF
}\endgroup
\expandafter\edef\csname cmapOT1\endcsname#1{%
\pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
}%
%
% \cmapOT1IT
\begingroup
\catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
\catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeX-OT1IT-0)
%%Title: (TeX-OT1IT-0 TeX OT1IT 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeX)
/Ordering (OT1IT)
/Supplement 0
>> def
/CMapName /TeX-OT1IT-0 def
/CMapType 2 def
1 begincodespacerange
<00> <7F>
endcodespacerange
8 beginbfrange
<00> <01> <0393>
<09> <0A> <03A8>
<25> <26> <0025>
<28> <3B> <0028>
<3F> <5B> <003F>
<5D> <5E> <005D>
<61> <7A> <0061>
<7B> <7C> <2013>
endbfrange
42 beginbfchar
<02> <0398>
<03> <039B>
<04> <039E>
<05> <03A0>
<06> <03A3>
<07> <03D2>
<08> <03A6>
<0B> <00660066>
<0C> <00660069>
<0D> <0066006C>
<0E> <006600660069>
<0F> <00660066006C>
<10> <0131>
<11> <0237>
<12> <0060>
<13> <00B4>
<14> <02C7>
<15> <02D8>
<16> <00AF>
<17> <02DA>
<18> <00B8>
<19> <00DF>
<1A> <00E6>
<1B> <0153>
<1C> <00F8>
<1D> <00C6>
<1E> <0152>
<1F> <00D8>
<21> <0021>
<22> <201D>
<23> <0023>
<24> <00A3>
<27> <2019>
<3C> <00A1>
<3D> <003D>
<3E> <00BF>
<5C> <201C>
<5F> <02D9>
<60> <2018>
<7D> <02DD>
<7E> <007E>
<7F> <00A8>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
%%EndResource
%%EOF
}\endgroup
\expandafter\edef\csname cmapOT1IT\endcsname#1{%
\pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
}%
%
% \cmapOT1TT
\begingroup
\catcode`\^^M=\active \def^^M{^^J}% Output line endings as the ^^J char.
\catcode`\%=12 \immediate\pdfobj stream {%!PS-Adobe-3.0 Resource-CMap
%%DocumentNeededResources: ProcSet (CIDInit)
%%IncludeResource: ProcSet (CIDInit)
%%BeginResource: CMap (TeX-OT1TT-0)
%%Title: (TeX-OT1TT-0 TeX OT1TT 0)
%%Version: 1.000
%%EndComments
/CIDInit /ProcSet findresource begin
12 dict begin
begincmap
/CIDSystemInfo
<< /Registry (TeX)
/Ordering (OT1TT)
/Supplement 0
>> def
/CMapName /TeX-OT1TT-0 def
/CMapType 2 def
1 begincodespacerange
<00> <7F>
endcodespacerange
5 beginbfrange
<00> <01> <0393>
<09> <0A> <03A8>
<21> <26> <0021>
<28> <5F> <0028>
<61> <7E> <0061>
endbfrange
32 beginbfchar
<02> <0398>
<03> <039B>
<04> <039E>
<05> <03A0>
<06> <03A3>
<07> <03D2>
<08> <03A6>
<0B> <2191>
<0C> <2193>
<0D> <0027>
<0E> <00A1>
<0F> <00BF>
<10> <0131>
<11> <0237>
<12> <0060>
<13> <00B4>
<14> <02C7>
<15> <02D8>
<16> <00AF>
<17> <02DA>
<18> <00B8>
<19> <00DF>
<1A> <00E6>
<1B> <0153>
<1C> <00F8>
<1D> <00C6>
<1E> <0152>
<1F> <00D8>
<20> <2423>
<27> <2019>
<60> <2018>
<7F> <00A8>
endbfchar
endcmap
CMapName currentdict /CMap defineresource pop
end
end
%%EndResource
%%EOF
}\endgroup
\expandafter\edef\csname cmapOT1TT\endcsname#1{%
\pdffontattr#1{/ToUnicode \the\pdflastobj\space 0 R}%
}%
\fi\fi
%
% This is what gets called when #5 of \setfont is empty.
\let\cmap\gobble
%
% (end of cmaps)
% Set the font macro #1 to the font named \fontprefix#2.
% #3 is the font's design size, #4 is a scale factor, #5 is the CMap
% encoding (only OT1, OT1IT and OT1TT are allowed, or empty to omit).
% Example:
% #1 = \textrm
% #2 = \rmshape
% #3 = 10
% #4 = \mainmagstep
% #5 = OT1
%
\def\setfont#1#2#3#4#5{%
\font#1=\fontprefix#2#3 scaled #4
\csname cmap#5\endcsname#1%
\ifx#2\ttshape\hyphenchar#1=-1 \fi
\ifx#2\ttbshape\hyphenchar#1=-1 \fi
\ifx#2\ttslshape\hyphenchar#1=-1 \fi
}
% Use cm as the default font prefix.
% To specify the font prefix, you must define \fontprefix
% before you read in texinfo.tex.
\ifx\fontprefix\thisisundefined
\def\fontprefix{cm}
\fi
% Support font families that don't use the same naming scheme as CM.
\def\rmshape{r}
\def\rmbshape{bx} % where the normal face is bold
\def\bfshape{b}
\def\bxshape{bx}
\def\ttshape{tt}
\def\ttbshape{tt}
\def\ttslshape{sltt}
\def\itshape{ti}
\def\itbshape{bxti}
\def\slshape{sl}
\def\slbshape{bxsl}
\def\sfshape{ss}
\def\sfbshape{ss}
\def\scshape{csc}
\def\scbshape{csc}
% Definitions for a main text size of 11pt. (The default in Texinfo.)
%
\def\definetextfontsizexi{%
% Text fonts (11.2pt, magstep1).
\def\textnominalsize{11pt}
\edef\mainmagstep{\magstephalf}
\setfont\textrm\rmshape{10}{\mainmagstep}{OT1}
\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT}
\setfont\textbf\bfshape{10}{\mainmagstep}{OT1}
\setfont\textit\itshape{10}{\mainmagstep}{OT1IT}
\setfont\textsl\slshape{10}{\mainmagstep}{OT1}
\setfont\textsf\sfshape{10}{\mainmagstep}{OT1}
\setfont\textsc\scshape{10}{\mainmagstep}{OT1}
\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT}
\font\texti=cmmi10 scaled \mainmagstep
\font\textsy=cmsy10 scaled \mainmagstep
\def\textecsize{1095}
% A few fonts for @defun names and args.
\setfont\defbf\bfshape{10}{\magstep1}{OT1}
\setfont\deftt\ttshape{10}{\magstep1}{OT1TT}
\setfont\defsl\slshape{10}{\magstep1}{OT1}
\setfont\defttsl\ttslshape{10}{\magstep1}{OT1TT}
\def\df{\let\ttfont=\deftt \let\bffont = \defbf
\let\ttslfont=\defttsl \let\slfont=\defsl \bf}
% Fonts for indices, footnotes, small examples (9pt).
\def\smallnominalsize{9pt}
\setfont\smallrm\rmshape{9}{1000}{OT1}
\setfont\smalltt\ttshape{9}{1000}{OT1TT}
\setfont\smallbf\bfshape{10}{900}{OT1}
\setfont\smallit\itshape{9}{1000}{OT1IT}
\setfont\smallsl\slshape{9}{1000}{OT1}
\setfont\smallsf\sfshape{9}{1000}{OT1}
\setfont\smallsc\scshape{10}{900}{OT1}
\setfont\smallttsl\ttslshape{10}{900}{OT1TT}
\font\smalli=cmmi9
\font\smallsy=cmsy9
\def\smallecsize{0900}
% Fonts for small examples (8pt).
\def\smallernominalsize{8pt}
\setfont\smallerrm\rmshape{8}{1000}{OT1}
\setfont\smallertt\ttshape{8}{1000}{OT1TT}
\setfont\smallerbf\bfshape{10}{800}{OT1}
\setfont\smallerit\itshape{8}{1000}{OT1IT}
\setfont\smallersl\slshape{8}{1000}{OT1}
\setfont\smallersf\sfshape{8}{1000}{OT1}
\setfont\smallersc\scshape{10}{800}{OT1}
\setfont\smallerttsl\ttslshape{10}{800}{OT1TT}
\font\smalleri=cmmi8
\font\smallersy=cmsy8
\def\smallerecsize{0800}
% Fonts for math mode superscripts (7pt).
\def\sevennominalsize{7pt}
\setfont\sevenrm\rmshape{7}{1000}{OT1}
\setfont\seventt\ttshape{10}{700}{OT1TT}
\setfont\sevenbf\bfshape{10}{700}{OT1}
\setfont\sevenit\itshape{7}{1000}{OT1IT}
\setfont\sevensl\slshape{10}{700}{OT1}
\setfont\sevensf\sfshape{10}{700}{OT1}
\setfont\sevensc\scshape{10}{700}{OT1}
\setfont\seventtsl\ttslshape{10}{700}{OT1TT}
\font\seveni=cmmi7
\font\sevensy=cmsy7
\def\sevenecsize{0700}
% Fonts for title page (20.4pt):
\def\titlenominalsize{20pt}
\setfont\titlerm\rmbshape{12}{\magstep3}{OT1}
\setfont\titleit\itbshape{10}{\magstep4}{OT1IT}
\setfont\titlesl\slbshape{10}{\magstep4}{OT1}
\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT}
\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT}
\setfont\titlesf\sfbshape{17}{\magstep1}{OT1}
\let\titlebf=\titlerm
\setfont\titlesc\scbshape{10}{\magstep4}{OT1}
\font\titlei=cmmi12 scaled \magstep3
\font\titlesy=cmsy10 scaled \magstep4
\def\titleecsize{2074}
% Chapter (and unnumbered) fonts (17.28pt).
\def\chapnominalsize{17pt}
\setfont\chaprm\rmbshape{12}{\magstep2}{OT1}
\setfont\chapit\itbshape{10}{\magstep3}{OT1IT}
\setfont\chapsl\slbshape{10}{\magstep3}{OT1}
\setfont\chaptt\ttbshape{12}{\magstep2}{OT1TT}
\setfont\chapttsl\ttslshape{10}{\magstep3}{OT1TT}
\setfont\chapsf\sfbshape{17}{1000}{OT1}
\let\chapbf=\chaprm
\setfont\chapsc\scbshape{10}{\magstep3}{OT1}
\font\chapi=cmmi12 scaled \magstep2
\font\chapsy=cmsy10 scaled \magstep3
\def\chapecsize{1728}
% Section fonts (14.4pt).
\def\secnominalsize{14pt}
\setfont\secrm\rmbshape{12}{\magstep1}{OT1}
\setfont\secrmnotbold\rmshape{12}{\magstep1}{OT1}
\setfont\secit\itbshape{10}{\magstep2}{OT1IT}
\setfont\secsl\slbshape{10}{\magstep2}{OT1}
\setfont\sectt\ttbshape{12}{\magstep1}{OT1TT}
\setfont\secttsl\ttslshape{10}{\magstep2}{OT1TT}
\setfont\secsf\sfbshape{12}{\magstep1}{OT1}
\let\secbf\secrm
\setfont\secsc\scbshape{10}{\magstep2}{OT1}
\font\seci=cmmi12 scaled \magstep1
\font\secsy=cmsy10 scaled \magstep2
\def\sececsize{1440}
% Subsection fonts (13.15pt).
\def\ssecnominalsize{13pt}
\setfont\ssecrm\rmbshape{12}{\magstephalf}{OT1}
\setfont\ssecit\itbshape{10}{1315}{OT1IT}
\setfont\ssecsl\slbshape{10}{1315}{OT1}
\setfont\ssectt\ttbshape{12}{\magstephalf}{OT1TT}
\setfont\ssecttsl\ttslshape{10}{1315}{OT1TT}
\setfont\ssecsf\sfbshape{12}{\magstephalf}{OT1}
\let\ssecbf\ssecrm
\setfont\ssecsc\scbshape{10}{1315}{OT1}
\font\sseci=cmmi12 scaled \magstephalf
\font\ssecsy=cmsy10 scaled 1315
\def\ssececsize{1200}
% Reduced fonts for @acronym in text (10pt).
\def\reducednominalsize{10pt}
\setfont\reducedrm\rmshape{10}{1000}{OT1}
\setfont\reducedtt\ttshape{10}{1000}{OT1TT}
\setfont\reducedbf\bfshape{10}{1000}{OT1}
\setfont\reducedit\itshape{10}{1000}{OT1IT}
\setfont\reducedsl\slshape{10}{1000}{OT1}
\setfont\reducedsf\sfshape{10}{1000}{OT1}
\setfont\reducedsc\scshape{10}{1000}{OT1}
\setfont\reducedttsl\ttslshape{10}{1000}{OT1TT}
\font\reducedi=cmmi10
\font\reducedsy=cmsy10
\def\reducedecsize{1000}
\textleading = 13.2pt % line spacing for 11pt CM
\textfonts % reset the current fonts
\rm
} % end of 11pt text font size definitions, \definetextfontsizexi
% Definitions to make the main text be 10pt Computer Modern, with
% section, chapter, etc., sizes following suit. This is for the GNU
% Press printing of the Emacs 22 manual. Maybe other manuals in the
% future. Used with @smallbook, which sets the leading to 12pt.
%
\def\definetextfontsizex{%
% Text fonts (10pt).
\def\textnominalsize{10pt}
\edef\mainmagstep{1000}
\setfont\textrm\rmshape{10}{\mainmagstep}{OT1}
\setfont\texttt\ttshape{10}{\mainmagstep}{OT1TT}
\setfont\textbf\bfshape{10}{\mainmagstep}{OT1}
\setfont\textit\itshape{10}{\mainmagstep}{OT1IT}
\setfont\textsl\slshape{10}{\mainmagstep}{OT1}
\setfont\textsf\sfshape{10}{\mainmagstep}{OT1}
\setfont\textsc\scshape{10}{\mainmagstep}{OT1}
\setfont\textttsl\ttslshape{10}{\mainmagstep}{OT1TT}
\font\texti=cmmi10 scaled \mainmagstep
\font\textsy=cmsy10 scaled \mainmagstep
\def\textecsize{1000}
% A few fonts for @defun names and args.
\setfont\defbf\bfshape{10}{\magstephalf}{OT1}
\setfont\deftt\ttshape{10}{\magstephalf}{OT1TT}
\setfont\defsl\slshape{10}{\magstephalf}{OT1}
\setfont\defttsl\ttslshape{10}{\magstephalf}{OT1TT}
\def\df{\let\ttfont=\deftt \let\bffont = \defbf
\let\slfont=\defsl \let\ttslfont=\defttsl \bf}
% Fonts for indices, footnotes, small examples (9pt).
\def\smallnominalsize{9pt}
\setfont\smallrm\rmshape{9}{1000}{OT1}
\setfont\smalltt\ttshape{9}{1000}{OT1TT}
\setfont\smallbf\bfshape{10}{900}{OT1}
\setfont\smallit\itshape{9}{1000}{OT1IT}
\setfont\smallsl\slshape{9}{1000}{OT1}
\setfont\smallsf\sfshape{9}{1000}{OT1}
\setfont\smallsc\scshape{10}{900}{OT1}
\setfont\smallttsl\ttslshape{10}{900}{OT1TT}
\font\smalli=cmmi9
\font\smallsy=cmsy9
\def\smallecsize{0900}
% Fonts for small examples (8pt).
\def\smallernominalsize{8pt}
\setfont\smallerrm\rmshape{8}{1000}{OT1}
\setfont\smallertt\ttshape{8}{1000}{OT1TT}
\setfont\smallerbf\bfshape{10}{800}{OT1}
\setfont\smallerit\itshape{8}{1000}{OT1IT}
\setfont\smallersl\slshape{8}{1000}{OT1}
\setfont\smallersf\sfshape{8}{1000}{OT1}
\setfont\smallersc\scshape{10}{800}{OT1}
\setfont\smallerttsl\ttslshape{10}{800}{OT1TT}
\font\smalleri=cmmi8
\font\smallersy=cmsy8
\def\smallerecsize{0800}
% Fonts for math mode superscripts (7pt).
\def\sevennominalsize{7pt}
\setfont\sevenrm\rmshape{7}{1000}{OT1}
\setfont\seventt\ttshape{10}{700}{OT1TT}
\setfont\sevenbf\bfshape{10}{700}{OT1}
\setfont\sevenit\itshape{7}{1000}{OT1IT}
\setfont\sevensl\slshape{10}{700}{OT1}
\setfont\sevensf\sfshape{10}{700}{OT1}
\setfont\sevensc\scshape{10}{700}{OT1}
\setfont\seventtsl\ttslshape{10}{700}{OT1TT}
\font\seveni=cmmi7
\font\sevensy=cmsy7
\def\sevenecsize{0700}
% Fonts for title page (20.4pt):
\def\titlenominalsize{20pt}
\setfont\titlerm\rmbshape{12}{\magstep3}{OT1}
\setfont\titleit\itbshape{10}{\magstep4}{OT1IT}
\setfont\titlesl\slbshape{10}{\magstep4}{OT1}
\setfont\titlett\ttbshape{12}{\magstep3}{OT1TT}
\setfont\titlettsl\ttslshape{10}{\magstep4}{OT1TT}
\setfont\titlesf\sfbshape{17}{\magstep1}{OT1}
\let\titlebf=\titlerm
\setfont\titlesc\scbshape{10}{\magstep4}{OT1}
\font\titlei=cmmi12 scaled \magstep3
\font\titlesy=cmsy10 scaled \magstep4
\def\titleecsize{2074}
% Chapter fonts (14.4pt).
\def\chapnominalsize{14pt}
\setfont\chaprm\rmbshape{12}{\magstep1}{OT1}
\setfont\chapit\itbshape{10}{\magstep2}{OT1IT}
\setfont\chapsl\slbshape{10}{\magstep2}{OT1}
\setfont\chaptt\ttbshape{12}{\magstep1}{OT1TT}
\setfont\chapttsl\ttslshape{10}{\magstep2}{OT1TT}
\setfont\chapsf\sfbshape{12}{\magstep1}{OT1}
\let\chapbf\chaprm
\setfont\chapsc\scbshape{10}{\magstep2}{OT1}
\font\chapi=cmmi12 scaled \magstep1
\font\chapsy=cmsy10 scaled \magstep2
\def\chapecsize{1440}
% Section fonts (12pt).
\def\secnominalsize{12pt}
\setfont\secrm\rmbshape{12}{1000}{OT1}
\setfont\secit\itbshape{10}{\magstep1}{OT1IT}
\setfont\secsl\slbshape{10}{\magstep1}{OT1}
\setfont\sectt\ttbshape{12}{1000}{OT1TT}
\setfont\secttsl\ttslshape{10}{\magstep1}{OT1TT}
\setfont\secsf\sfbshape{12}{1000}{OT1}
\let\secbf\secrm
\setfont\secsc\scbshape{10}{\magstep1}{OT1}
\font\seci=cmmi12
\font\secsy=cmsy10 scaled \magstep1
\def\sececsize{1200}
% Subsection fonts (10pt).
\def\ssecnominalsize{10pt}
\setfont\ssecrm\rmbshape{10}{1000}{OT1}
\setfont\ssecit\itbshape{10}{1000}{OT1IT}
\setfont\ssecsl\slbshape{10}{1000}{OT1}
\setfont\ssectt\ttbshape{10}{1000}{OT1TT}
\setfont\ssecttsl\ttslshape{10}{1000}{OT1TT}
\setfont\ssecsf\sfbshape{10}{1000}{OT1}
\let\ssecbf\ssecrm
\setfont\ssecsc\scbshape{10}{1000}{OT1}
\font\sseci=cmmi10
\font\ssecsy=cmsy10
\def\ssececsize{1000}
% Reduced fonts for @acronym in text (9pt).
\def\reducednominalsize{9pt}
\setfont\reducedrm\rmshape{9}{1000}{OT1}
\setfont\reducedtt\ttshape{9}{1000}{OT1TT}
\setfont\reducedbf\bfshape{10}{900}{OT1}
\setfont\reducedit\itshape{9}{1000}{OT1IT}
\setfont\reducedsl\slshape{9}{1000}{OT1}
\setfont\reducedsf\sfshape{9}{1000}{OT1}
\setfont\reducedsc\scshape{10}{900}{OT1}
\setfont\reducedttsl\ttslshape{10}{900}{OT1TT}
\font\reducedi=cmmi9
\font\reducedsy=cmsy9
\def\reducedecsize{0900}
\divide\parskip by 2 % reduce space between paragraphs
\textleading = 12pt % line spacing for 10pt CM
\textfonts % reset the current fonts
\rm
} % end of 10pt text font size definitions, \definetextfontsizex
% Fonts for short table of contents.
\setfont\shortcontrm\rmshape{12}{1000}{OT1}
\setfont\shortcontbf\bfshape{10}{\magstep1}{OT1} % no cmb12
\setfont\shortcontsl\slshape{12}{1000}{OT1}
\setfont\shortconttt\ttshape{12}{1000}{OT1TT}
% We provide the user-level command
% @fonttextsize 10
% (or 11) to redefine the text font size. pt is assumed.
%
\def\xiword{11}
\def\xword{10}
\def\xwordpt{10pt}
%
\parseargdef\fonttextsize{%
\def\textsizearg{#1}%
%\wlog{doing @fonttextsize \textsizearg}%
%
% Set \globaldefs so that documents can use this inside @tex, since
% makeinfo 4.8 does not support it, but we need it nonetheless.
%
\begingroup \globaldefs=1
\ifx\textsizearg\xword \definetextfontsizex
\else \ifx\textsizearg\xiword \definetextfontsizexi
\else
\errhelp=\EMsimple
\errmessage{@fonttextsize only supports `10' or `11', not `\textsizearg'}
\fi\fi
\endgroup
}
%
% Change the current font style to #1, remembering it in \curfontstyle.
% For now, we do not accumulate font styles: @b{@i{foo}} prints foo in
% italics, not bold italics.
%
\def\setfontstyle#1{%
\def\curfontstyle{#1}% not as a control sequence, because we are \edef'd.
\csname #1font\endcsname % change the current font
}
\def\rm{\fam=0 \setfontstyle{rm}}
\def\it{\fam=\itfam \setfontstyle{it}}
\def\sl{\fam=\slfam \setfontstyle{sl}}
\def\bf{\fam=\bffam \setfontstyle{bf}}\def\bfstylename{bf}
\def\tt{\fam=\ttfam \setfontstyle{tt}}
% Texinfo sort of supports the sans serif font style, which plain TeX does not.
% So we set up a \sf.
\newfam\sffam
\def\sf{\fam=\sffam \setfontstyle{sf}}
% We don't need math for this font style.
\def\ttsl{\setfontstyle{ttsl}}
% In order for the font changes to affect most math symbols and letters,
% we have to define the \textfont of the standard families.
% We don't bother to reset \scriptscriptfont; awaiting user need.
%
\def\resetmathfonts{%
\textfont0=\rmfont \textfont1=\ifont \textfont2=\syfont
\textfont\itfam=\itfont \textfont\slfam=\slfont \textfont\bffam=\bffont
\textfont\ttfam=\ttfont \textfont\sffam=\sffont
%
% Fonts for superscript. Note that the 7pt fonts are used regardless
% of the current font size.
\scriptfont0=\sevenrm \scriptfont1=\seveni \scriptfont2=\sevensy
\scriptfont\itfam=\sevenit \scriptfont\slfam=\sevensl
\scriptfont\bffam=\sevenbf \scriptfont\ttfam=\seventt
\scriptfont\sffam=\sevensf
}
% \defineassignfonts{SIZE} -
% Define sequence \assignfontsSIZE, which switches between font sizes
% by redefining the meanings of \STYLEfont. (Just \STYLE additionally sets
% the current \fam for math mode.)
%
\def\defineassignfonts#1{%
\expandafter\edef\csname assignfonts#1\endcsname{%
\let\noexpand\rmfont\csname #1rm\endcsname
\let\noexpand\itfont\csname #1it\endcsname
\let\noexpand\slfont\csname #1sl\endcsname
\let\noexpand\bffont\csname #1bf\endcsname
\let\noexpand\ttfont\csname #1tt\endcsname
\let\noexpand\smallcaps\csname #1sc\endcsname
\let\noexpand\sffont \csname #1sf\endcsname
\let\noexpand\ifont \csname #1i\endcsname
\let\noexpand\syfont \csname #1sy\endcsname
\let\noexpand\ttslfont\csname #1ttsl\endcsname
}
}
\def\assignfonts#1{%
\csname assignfonts#1\endcsname
}
\newif\ifrmisbold
% Select smaller font size with the current style. Used to change font size
% in, e.g., the LaTeX logo and acronyms. If we are using bold fonts for
% normal roman text, also use bold fonts for roman text in the smaller size.
\def\switchtolllsize{%
\expandafter\assignfonts\expandafter{\lllsize}%
\ifrmisbold
\let\rmfont\bffont
\fi
\csname\curfontstyle\endcsname
}%
\def\switchtolsize{%
\expandafter\assignfonts\expandafter{\lsize}%
\ifrmisbold
\let\rmfont\bffont
\fi
\csname\curfontstyle\endcsname
}%
% Define the font-changing commands (all called \...fonts).
% Each font-changing command also sets the names \lsize (one size lower)
% and \lllsize (three sizes lower). These relative commands are used
% in, e.g., the LaTeX logo and acronyms.
%
% Note: The fonts used for \ifont are for "math italics" (\itfont is for
% italics in regular text). \syfont is also used in math mode only.
%
\def\definefontsetatsize#1#2#3#4#5{%
\defineassignfonts{#1}%
\expandafter\def\csname #1fonts\endcsname{%
\def\curfontsize{#1}%
\def\lsize{#2}\def\lllsize{#3}%
\csname rmisbold#5\endcsname
\csname assignfonts#1\endcsname
\resetmathfonts
\setleading{#4}%
}}
\definefontsetatsize{text} {reduced}{smaller}{\textleading}{false}
\definefontsetatsize{title} {chap} {subsec} {27pt} {true}
\definefontsetatsize{chap} {sec} {text} {19pt} {true}
\definefontsetatsize{sec} {subsec} {reduced}{17pt} {true}
\definefontsetatsize{ssec} {text} {small} {15pt} {true}
\definefontsetatsize{reduced}{small} {smaller}{10.5pt}{false}
\definefontsetatsize{small} {smaller}{smaller}{10.5pt}{false}
\definefontsetatsize{smaller}{smaller}{smaller}{9.5pt} {false}
\def\titlefont#1{{\titlefonts\rm #1}}
\let\subsecfonts = \ssecfonts
\let\subsubsecfonts = \ssecfonts
% Define these just so they can be easily changed for other fonts.
\def\angleleft{$\langle$}
\def\angleright{$\rangle$}
% Set the fonts to use with the @small... environments.
\let\smallexamplefonts = \smallfonts
% About \smallexamplefonts. If we use \smallfonts (9pt), @smallexample
% can fit this many characters:
% 8.5x11=86 smallbook=72 a4=90 a5=69
% If we use \scriptfonts (8pt), then we can fit this many characters:
% 8.5x11=90+ smallbook=80 a4=90+ a5=77
% For me, subjectively, the few extra characters that fit aren't worth
% the additional smallness of 8pt. So I'm making the default 9pt.
%
% By the way, for comparison, here's what fits with @example (10pt):
% 8.5x11=71 smallbook=60 a4=75 a5=58
% --karl, 24jan03.
% Set up the default fonts, so we can use them for creating boxes.
%
\definetextfontsizexi
% Check if we are currently using a typewriter font. Since all the
% Computer Modern typewriter fonts have zero interword stretch (and
% shrink), and it is reasonable to expect all typewriter fonts to have
% this property, we can check that font parameter. #1 is what to
% print if we are indeed using \tt; #2 is what to print otherwise.
\def\ifusingtt#1#2{\ifdim \fontdimen3\font=0pt #1\else #2\fi}
% Same as above, but check for italic font. Actually this also catches
% non-italic slanted fonts since it is impossible to distinguish them from
% italic fonts. But since this is only used by $ and it uses \sl anyway
% this is not a problem.
\def\ifusingit#1#2{\ifdim \fontdimen1\font>0pt #1\else #2\fi}
% Check if internal flag is clear, i.e. has not been @set.
\def\ifflagclear#1#2#3{%
\expandafter\ifx\csname SET#1\endcsname\relax
#2\else#3\fi
}
{
\catcode`\'=\active
\catcode`\`=\active
\gdef\setcodequotes{\let`\codequoteleft \let'\codequoteright}
\gdef\setregularquotes{\let`\lq \let'\rq}
}
\setregularquotes
% output for ' in @code
% in tt font hex 0D (undirected) or 27 (curly right quote)
%
\def\codequoteright{%
\ifusingtt
{\ifflagclear{txicodequoteundirected}%
{\ifflagclear{codequoteundirected}%
{'}%
{\char"0D }}%
{\char"0D }}%
{'}%
}
% output for ` in @code
% in tt font hex 12 (grave accent) or 60 (curly left quote)
% \relax disables Spanish ligatures ?` and !` of \tt font.
%
\def\codequoteleft{%
\ifusingtt
{\ifflagclear{txicodequotebacktick}%
{\ifflagclear{codequotebacktick}%
{\relax`}%
{\char"12 }}%
{\char"12 }}%
{\relax`}%
}
% Commands to set the quote options.
%
\parseargdef\codequoteundirected{%
\def\temp{#1}%
\ifx\temp\onword
\expandafter\let\csname SETtxicodequoteundirected\endcsname
= t%
\else\ifx\temp\offword
\expandafter\let\csname SETtxicodequoteundirected\endcsname
= \relax
\else
\errhelp = \EMsimple
\errmessage{Unknown @codequoteundirected value `\temp', must be on|off}%
\fi\fi
}
\parseargdef\codequotebacktick{%
\def\temp{#1}%
\ifx\temp\onword
\expandafter\let\csname SETtxicodequotebacktick\endcsname
= t%
\else\ifx\temp\offword
\expandafter\let\csname SETtxicodequotebacktick\endcsname
= \relax
\else
\errhelp = \EMsimple
\errmessage{Unknown @codequotebacktick value `\temp', must be on|off}%
\fi\fi
}
% Turn them on by default
\let\SETtxicodequoteundirected = t
\let\SETtxicodequotebacktick = t
% [Knuth] pp. 380,381,391, disable Spanish ligatures ?` and !` of \tt font.
\def\noligaturesquoteleft{\relax\lq}
% Count depth in font-changes, for error checks
\newcount\fontdepth \fontdepth=0
% Font commands.
% #1 is the font command (\sl or \it), #2 is the text to slant.
% If we are in a monospaced environment, however, 1) always use \ttsl,
% and 2) do not add an italic correction.
\def\dosmartslant#1#2{%
\ifusingtt
{{\ttsl #2}\let\next=\relax}%
{\def\next{{#1#2}\smartitaliccorrection}}%
\next
}
\def\smartslanted{\dosmartslant\sl}
\def\smartitalic{\dosmartslant\it}
% Output an italic correction unless the following character is such as
% not to need one.
\def\smartitaliccorrection{\futurelet\next\smartitaliccorrectionx}
\def\smartitaliccorrectionx{%
\ifx\next,%
\else\ifx\next-%
\else\ifx\next.%
\else\ifx\next\.%
\else\ifx\next\comma%
\else\ptexslash
\fi\fi\fi\fi\fi
\aftersmartic
}
% @cite unconditionally uses \sl with \smartitaliccorrection.
\def\cite#1{{\sl #1}\smartitaliccorrection}
% @var unconditionally uses \sl. This gives consistency for
% parameter names whether they are in @def, @table @code or a
% regular paragraph.
% To get ttsl font for @var when used in code context, @set txicodevaristt.
% The \null is to reset \spacefactor.
\def\aftersmartic{}
\def\var#1{%
\let\saveaftersmartic = \aftersmartic
\def\aftersmartic{\null\let\aftersmartic=\saveaftersmartic}%
%
\ifflagclear{txicodevaristt}%
{\def\varnext{{{\sl #1}}\smartitaliccorrection}}%
{\def\varnext{\smartslanted{#1}}}%
\varnext
}
% To be removed after next release
\def\SETtxicodevaristt{}% @set txicodevaristt
\let\i=\smartitalic
\let\slanted=\smartslanted
\let\dfn=\smartslanted
\let\emph=\smartitalic
% @r for roman font, used for code comment
\def\r#1{{%
\usenormaldash % get --, --- ligatures even if in @code
\defcharsdefault % in case on def line
\rm #1}}
{\catcode`-=\active \gdef\usenormaldash{\let-\normaldash}}
% @sc, undocumented @ii.
\def\sc#1{{\smallcaps#1}} % smallcaps font
\def\ii#1{{\it #1}} % italic font
% @b, explicit bold. Also @strong.
\def\b#1{{\bf #1}}
\let\strong=\b
% @sansserif, explicit sans.
\def\sansserif#1{{\sf #1}}
\newif\iffrenchspacing
\frenchspacingfalse
% Set sfcode to normal for the chars that usually have another value.
% Can't use plain's \frenchspacing because it uses the `\x notation, and
% sometimes \x has an active definition that messes things up.
%
\catcode`@=11
\def\plainfrenchspacing{%
\iffrenchspacing\else
\frenchspacingtrue
\sfcode`\.=\@m \sfcode`\?=\@m \sfcode`\!=\@m
\sfcode`\:=\@m \sfcode`\;=\@m \sfcode`\,=\@m
\def\endofsentencespacefactor{1000}% for @. and friends
\fi
}
\def\plainnonfrenchspacing{%
\iffrenchspacing
\frenchspacingfalse
\sfcode`\.3000\sfcode`\?3000\sfcode`\!3000
\sfcode`\:2000\sfcode`\;1500\sfcode`\,1250
\def\endofsentencespacefactor{3000}% for @. and friends
\fi
}
\catcode`@=\other
\def\endofsentencespacefactor{3000}% default
% @frenchspacing on|off says whether to put extra space after punctuation.
%
\def\onword{on}
\def\offword{off}
%
\let\frenchspacingsetting\plainnonfrenchspacing % used in output routine
\parseargdef\frenchspacing{%
\def\temp{#1}%
\ifx\temp\onword \let\frenchspacingsetting\plainfrenchspacing
\else\ifx\temp\offword \let\frenchspacingsetting\plainnonfrenchspacing
\else
\errhelp = \EMsimple
\errmessage{Unknown @frenchspacing option `\temp', must be on|off}%
\fi\fi
\frenchspacingsetting
}
% @t, explicit typewriter.
\def\t#1{%
{\tt \defcharsdefault \plainfrenchspacing #1}%
\null
}
% @samp.
\def\samp#1{{\setcodequotes\lq\tclose{#1}\rq\null}}
% @indicateurl is \samp, that is, with quotes.
\let\indicateurl=\samp
% @code (and similar) prints in typewriter, but with spaces the same
% size as normal in the surrounding text, without hyphenation, etc.
% This is a subroutine for that.
\def\tclose#1{%
{%
% Change normal interword space to be same as for the current font.
\spaceskip = \fontdimen2\font
%
% Switch to typewriter.
\tt
%
% `\ ' produces the large typewriter interword space.
\def\ {{\spaceskip = 0pt{} }}%
%
\plainfrenchspacing
#1%
}%
\null % reset spacefactor to 1000
}
% This is for LuaTeX: It is not sufficient to disable hyphenation at
% explicit dashes by setting `\hyphenchar` to -1.
\def\dashnobreak{%
\normaldash
\penalty 10000 }
% We must turn on hyphenation at `-' and `_' in @code.
% Otherwise, it is too hard to avoid overfull hboxes
% in the Emacs manual, the Library manual, etc.
% We explicitly allow hyphenation at these characters
% using \discretionary.
%
% Hyphenation at - and hyphenation within words was turned off
% by default for the tt fonts using the \hyphenchar parameter of TeX.
{
\catcode`\-=\active \catcode`\_=\active
\catcode`\'=\active \catcode`\`=\active
\global\let'=\rq \global\let`=\lq % default definitions
%
\global\def\code{\begingroup
\setcodequotes
\catcode\dashChar=\active \catcode\underChar=\active
\ifallowcodebreaks
\let-\codedash
\let_\codeunder
\else
\let-\dashnobreak
\let_\realunder
\fi
\codex
}
%
\gdef\codedash{\futurelet\next\codedashfinish}
\gdef\codedashfinish{%
\normaldash % always output the dash character itself.
%
% Now, output a discretionary to allow a line break, unless
% (a) the next character is a -, or
% (b) the preceding character is a -, or
% (c) we are at the start of the string.
% In both cases (b) and (c), \codedashnobreak should be set to \codedash.
%
% E.g., given --posix, we do not want to allow a break after either -.
% Given --foo-bar, we do want to allow a break between the - and the b.
\ifx\next\codedash \else
\ifx\codedashnobreak\codedash
\else \discretionary{}{}{}\fi
\fi
% we need the space after the = for the case when \next itself is a
% space token; it would get swallowed otherwise. As in @code{- a}.
\global\let\codedashnobreak= \next
}
}
\def\normaldash{-}
%
\def\codex #1{\tclose{%
% Given -foo (with a single dash), we do not want to allow a break
% after the -. \codedashnobreak is set to the first character in
% @code.
\futurelet\codedashnobreak\relax
#1%
}\endgroup}
\def\codeunder{%
% this is all so @math{@code{var_name}+1} can work. In math mode, _
% is "active" (mathcode"8000) and \normalunderscore (or \char95, etc.)
% will therefore expand the active definition of _, which is us
% (inside @code that is), therefore an endless loop.
\ifusingtt{\ifmmode
\mathchar"075F % class 0=ordinary, family 7=ttfam, pos 0x5F=_.
\else\normalunderscore \fi
\discretionary{}{}{}}%
{\_}%
}
% An additional complication: the above will allow breaks after, e.g.,
% each of the four underscores in __typeof__. This is bad.
% @allowcodebreaks provides a document-level way to turn breaking at -
% and _ on and off.
%
\newif\ifallowcodebreaks \allowcodebreakstrue
\def\keywordtrue{true}
\def\keywordfalse{false}
\parseargdef\allowcodebreaks{%
\def\txiarg{#1}%
\ifx\txiarg\keywordtrue
\allowcodebreakstrue
\else\ifx\txiarg\keywordfalse
\allowcodebreaksfalse
\else
\errhelp = \EMsimple
\errmessage{Unknown @allowcodebreaks option `\txiarg', must be true|false}%
\fi\fi
}
% For @command, @env, @file, @option quotes seem unnecessary,
% so use \code rather than \samp.
\let\command=\code
\let\env=\code
\let\file=\code
\let\option=\code
% @uref (abbreviation for `urlref') aka @url takes an optional
% (comma-separated) second argument specifying the text to display and
% an optional third arg as text to display instead of (rather than in
% addition to) the url itself. First (mandatory) arg is the url.
% TeX-only option to allow changing PDF output to show only the second
% arg (if given), and not the url (which is then just the link target).
\newif\ifurefurlonlylink
% The default \pretolerance setting stops the penalty inserted in
% \urefallowbreak being a discouragement to line breaking. Set it to
% a negative value for this paragraph only. Hopefully this does not
% conflict with redefinitions of \par done elsewhere.
\def\nopretolerance{%
\pretolerance=-1
\def\par{\endgraf\pretolerance=100 \let\par\endgraf}%
}
% The main macro is \urefbreak, which allows breaking at expected
% places within the url.
\def\urefbreak{\nopretolerance \begingroup \urefcatcodes \dourefbreak}
\let\uref=\urefbreak
%
\def\dourefbreak#1{\urefbreakfinish #1,,,\finish}
\def\urefbreakfinish#1,#2,#3,#4\finish{% doesn't work in @example
\unsepspaces
\pdfurl{#1}%
\setbox0 = \hbox{\ignorespaces #3}%
\ifdim\wd0 > 0pt
\unhbox0 % third arg given, show only that
\else
\setbox0 = \hbox{\ignorespaces #2}% look for second arg
\ifdim\wd0 > 0pt
\ifpdf
% For pdfTeX and LuaTeX
\ifurefurlonlylink
% PDF plus option to not display url, show just arg
\unhbox0
\else
% PDF, normally display both arg and url for consistency,
% visibility, if the pdf is eventually used to print, etc.
\unhbox0\ (\urefcode{#1})%
\fi
\else
\ifx\XeTeXrevision\thisisundefined
\unhbox0\ (\urefcode{#1})% DVI, always show arg and url
\else
% For XeTeX
\ifurefurlonlylink
% PDF plus option to not display url, show just arg
\unhbox0
\else
% PDF, normally display both arg and url for consistency,
% visibility, if the pdf is eventually used to print, etc.
\unhbox0\ (\urefcode{#1})%
\fi
\fi
\fi
\else
\urefcode{#1}% only url given, so show it
\fi
\fi
\endlink
\endgroup}
% Allow line breaks around only a few characters (only).
\def\urefcatcodes{%
\catcode`\&=\active \catcode`\.=\active
\catcode`\#=\active \catcode`\?=\active
\catcode`\/=\active
}
{
\urefcatcodes
%
\global\def\urefcode{\begingroup
\setcodequotes
\urefcatcodes
\let&\urefcodeamp
\let.\urefcodedot
\let#\urefcodehash
\let?\urefcodequest
\let/\urefcodeslash
\codex
}
%
% By default, they are just regular characters.
\global\def&{\normalamp}
\global\def.{\normaldot}
\global\def#{\normalhash}
\global\def?{\normalquest}
\global\def/{\normalslash}
}
\def\urefcodeamp{\urefprebreak \&\urefpostbreak}
\def\urefcodedot{\urefprebreak .\urefpostbreak}
\def\urefcodehash{\urefprebreak \#\urefpostbreak}
\def\urefcodequest{\urefprebreak ?\urefpostbreak}
\def\urefcodeslash{\futurelet\next\urefcodeslashfinish}
{
\catcode`\/=\active
\global\def\urefcodeslashfinish{%
\urefprebreak \slashChar
% Allow line break only after the final / in a sequence of
% slashes, to avoid line break between the slashes in http://.
\ifx\next/\else \urefpostbreak \fi
}
}
% By default we'll break after the special characters, but some people like to
% break before the special chars, so allow that. Also allow no breaking at
% all, for manual control.
%
\parseargdef\urefbreakstyle{%
\def\txiarg{#1}%
\ifx\txiarg\wordnone
\def\urefprebreak{\nobreak}\def\urefpostbreak{\nobreak}
\else\ifx\txiarg\wordbefore
\def\urefprebreak{\urefallowbreak}\def\urefpostbreak{\nobreak}
\else\ifx\txiarg\wordafter
\def\urefprebreak{\nobreak}\def\urefpostbreak{\urefallowbreak}
\else
\errhelp = \EMsimple
\errmessage{Unknown @urefbreakstyle setting `\txiarg'}%
\fi\fi\fi
}
\def\wordafter{after}
\def\wordbefore{before}
\def\wordnone{none}
% Allow a ragged right output to aid breaking long URL's. There can
% be a break at the \allowbreak with no extra glue (if the existing stretch in
% the line is sufficient), a break at the \penalty with extra glue added
% at the end of the line, or no break at all here.
% Changing the value of the penalty and/or the amount of stretch affects how
% preferable one choice is over the other.
\def\urefallowbreak{%
\penalty0\relax
\hskip 0pt plus 2 em\relax
\penalty1000\relax
\hskip 0pt plus -2 em\relax
}
\urefbreakstyle after
% @url synonym for @uref, since that's how everyone uses it.
%
\let\url=\uref
% rms does not like angle brackets --karl, 17may97.
% So now @email is just like @uref, unless we are pdf.
%
%\def\email#1{\angleleft{\tt #1}\angleright}
\ifpdforxetex
\def\email#1{\doemail#1,,\finish}
\def\doemail#1,#2,#3\finish{\begingroup
\unsepspaces
\pdfurl{mailto:#1}%
\setbox0 = \hbox{\ignorespaces #2}%
\ifdim\wd0>0pt\unhbox0\else\code{#1}\fi
\endlink
\endgroup}
\else
\let\email=\uref
\fi
% @kbdinputstyle -- arg is `distinct' (@kbd uses slanted tty font always),
% `example' (@kbd uses ttsl only inside of @example and friends),
% or `code' (@kbd uses normal tty font always).
\parseargdef\kbdinputstyle{%
\def\txiarg{#1}%
\ifx\txiarg\worddistinct
\gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\ttsl}%
\else\ifx\txiarg\wordexample
\gdef\kbdexamplefont{\ttsl}\gdef\kbdfont{\tt}%
\else\ifx\txiarg\wordcode
\gdef\kbdexamplefont{\tt}\gdef\kbdfont{\tt}%
\else
\errhelp = \EMsimple
\errmessage{Unknown @kbdinputstyle setting `\txiarg'}%
\fi\fi\fi
}
\def\worddistinct{distinct}
\def\wordexample{example}
\def\wordcode{code}
% Default is `distinct'.
\kbdinputstyle distinct
\def\kbd#1{%
\tclose{\kbdfont\setcodequotes#1}%
}
% definition of @key that produces a lozenge. Doesn't adjust to text size.
%\setfont\keyrm\rmshape{8}{1000}{OT1}
%\font\keysy=cmsy9
%\def\key#1{{\keyrm\textfont2=\keysy \leavevmode\hbox{%
% \raise0.4pt\hbox{\angleleft}\kern-.08em\vtop{%
% \vbox{\hrule\kern-0.4pt
% \hbox{\raise0.4pt\hbox{\vphantom{\angleleft}}#1}}%
% \kern-0.4pt\hrule}%
% \kern-.06em\raise0.4pt\hbox{\angleright}}}}
% definition of @key with no lozenge.
%
\def\key#1{{\setregularquotes \tt #1}\null}
% @clicksequence{File @click{} Open ...}
\def\clicksequence#1{\begingroup #1\endgroup}
% @clickstyle @arrow (by default)
\parseargdef\clickstyle{\def\click{#1}}
\def\click{\arrow}
% Typeset a dimension, e.g., `in' or `pt'. The only reason for the
% argument is to make the input look right: @dmn{pt} instead of @dmn{}pt.
%
\def\dmn#1{\thinspace #1}
% @acronym for "FBI", "NATO", and the like.
% We print this one point size smaller, since it's intended for
% all-uppercase.
%
\def\acronym#1{\doacronym #1,,\finish}
\def\doacronym#1,#2,#3\finish{%
{\switchtolsize #1}%
\def\temp{#2}%
\ifx\temp\empty \else
\space ({\unsepspaces \ignorespaces \temp \unskip})%
\fi
\null % reset \spacefactor=1000
}
% @abbr for "Comput. J." and the like.
% No font change, but don't do end-of-sentence spacing.
%
\def\abbr#1{\doabbr #1,,\finish}
\def\doabbr#1,#2,#3\finish{%
{\plainfrenchspacing #1}%
\def\temp{#2}%
\ifx\temp\empty \else
\space ({\unsepspaces \ignorespaces \temp \unskip})%
\fi
\null % reset \spacefactor=1000
}
% @asis just yields its argument. Used with @table, for example.
%
\def\asis#1{#1}
% @math outputs its argument in math mode.
%
% One complication: _ usually means subscripts, but it could also mean
% an actual _ character, as in @math{@var{some_variable} + 1}. So make
% _ active, and distinguish by seeing if the current family is \slfam,
% which is what @var uses.
{
\catcode`\_ = \active
\gdef\mathunderscore{%
\catcode`\_=\active
\def_{\ifnum\fam=\slfam \_\else\sb\fi}%
}
}
% Another complication: we want \\ (and @\) to output a math (or tt) \.
% FYI, plain.tex uses \\ as a temporary control sequence (for no
% particular reason), but this is not advertised and we don't care.
%
% The \mathchar is class=0=ordinary, family=7=ttfam, position=5C=\.
\def\mathbackslash{\ifnum\fam=\ttfam \mathchar"075C \else\backslash \fi}
%
\def\math{%
\ifmmode\else % only go into math if not in math mode already
\tex
\mathunderscore
\let\\ = \mathbackslash
\mathactive
% make the texinfo accent commands work in math mode
\let\"=\ddot
\let\'=\acute
\let\==\bar
\let\^=\hat
\let\`=\grave
\let\u=\breve
\let\v=\check
\let\~=\tilde
\let\dotaccent=\dot
% have to provide another name for sup operator
\let\mathopsup=\sup
$\expandafter\finishmath\fi
}
\def\finishmath#1{#1$\endgroup} % Close the group opened by \tex.
% Some active characters (such as <) are spaced differently in math.
% We have to reset their definitions in case the @math was an argument
% to a command which sets the catcodes (such as @item or @section).
%
{
\catcode`^ = \active
\catcode`< = \active
\catcode`> = \active
\catcode`+ = \active
\catcode`' = \active
\gdef\mathactive{%
\let^ = \ptexhat
\let< = \ptexless
\let> = \ptexgtr
\let+ = \ptexplus
\let' = \ptexquoteright
}
}
% for @sub and @sup, if in math mode, just do a normal sub/superscript.
% If in text, use math to place as sub/superscript, but switch
% into text mode, with smaller fonts. This is a different font than the
% one used for real math sub/superscripts (8pt vs. 7pt), but let's not
% fix it (significant additions to font machinery) until someone notices.
%
\def\sub{\ifmmode \expandafter\sb \else \expandafter\finishsub\fi}
\def\finishsub#1{$\sb{\hbox{\switchtolllsize #1}}$}%
%
\def\sup{\ifmmode \expandafter\ptexsp \else \expandafter\finishsup\fi}
\def\finishsup#1{$\ptexsp{\hbox{\switchtolllsize #1}}$}%
% provide this command from LaTeX as it is very common
\def\frac#1#2{{{#1}\over{#2}}}
% @displaymath.
% \globaldefs is needed to recognize the end lines in \tex and
% \end tex. Set \thisenv as @end displaymath is seen before @end tex.
{\obeylines
\globaldefs=1
\envdef\displaymath{%
\tex%
\def\thisenv{\displaymath}%
\begingroup\let\end\displaymathend%
$$%
}
\def\displaymathend{$$\endgroup\end}%
\def\Edisplaymath{%
\def\thisenv{\tex}%
\end tex
}}
% @inlinefmt{FMTNAME,PROCESSED-TEXT} and @inlineraw{FMTNAME,RAW-TEXT}.
% Ignore unless FMTNAME == tex; then it is like @iftex and @tex,
% except specified as a normal braced arg, so no newlines to worry about.
%
\def\outfmtnametex{tex}
%
\long\def\inlinefmt#1{\doinlinefmt #1,\finish}
\long\def\doinlinefmt#1,#2,\finish{%
\def\inlinefmtname{#1}%
\ifx\inlinefmtname\outfmtnametex \ignorespaces #2\fi
}
%
% @inlinefmtifelse{FMTNAME,THEN-TEXT,ELSE-TEXT} expands THEN-TEXT if
% FMTNAME is tex, else ELSE-TEXT.
\long\def\inlinefmtifelse#1{\doinlinefmtifelse #1,,,\finish}
\long\def\doinlinefmtifelse#1,#2,#3,#4,\finish{%
\def\inlinefmtname{#1}%
\ifx\inlinefmtname\outfmtnametex \ignorespaces #2\else \ignorespaces #3\fi
}
%
% For raw, must switch into @tex before parsing the argument, to avoid
% setting catcodes prematurely. Doing it this way means that, for
% example, @inlineraw{html, foo{bar} gets a parse error instead of being
% ignored. But this isn't important because if people want a literal
% *right* brace they would have to use a command anyway, so they may as
% well use a command to get a left brace too. We could re-use the
% delimiter character idea from \verb, but it seems like overkill.
%
\long\def\inlineraw{\tex \doinlineraw}
\long\def\doinlineraw#1{\doinlinerawtwo #1,\finish}
\def\doinlinerawtwo#1,#2,\finish{%
\def\inlinerawname{#1}%
\ifx\inlinerawname\outfmtnametex \ignorespaces #2\fi
\endgroup % close group opened by \tex.
}
% @inlineifset{VAR, TEXT} expands TEXT if VAR is @set.
%
\long\def\inlineifset#1{\doinlineifset #1,\finish}
\long\def\doinlineifset#1,#2,\finish{%
\def\inlinevarname{#1}%
\expandafter\ifx\csname SET\inlinevarname\endcsname\relax
\else\ignorespaces#2\fi
}
% @inlineifclear{VAR, TEXT} expands TEXT if VAR is not @set.
%
\long\def\inlineifclear#1{\doinlineifclear #1,\finish}
\long\def\doinlineifclear#1,#2,\finish{%
\def\inlinevarname{#1}%
\expandafter\ifx\csname SET\inlinevarname\endcsname\relax \ignorespaces#2\fi
}
\message{glyphs,}
% and logos.
% @@ prints an @, as does @atchar{}.
\def\@{\char64 }
\let\atchar=\@
% @{ @} @lbracechar{} @rbracechar{} all generate brace characters.
\def\lbracechar{{\ifusingtt{\char123}{\ensuremath\lbrace}}}
\def\rbracechar{{\ifusingtt{\char125}{\ensuremath\rbrace}}}
\let\{=\lbracechar
\let\}=\rbracechar
% @comma{} to avoid , parsing problems.
\let\comma = ,
% Accents: @, @dotaccent @ringaccent @ubaraccent @udotaccent
% Others are defined by plain TeX: @` @' @" @^ @~ @= @u @v @H.
\let\, = \ptexc
\let\dotaccent = \ptexdot
\def\ringaccent#1{{\accent23 #1}}
\let\tieaccent = \ptext
\let\ubaraccent = \ptexb
\let\udotaccent = \d
% Other special characters: @questiondown @exclamdown @ordf @ordm
% Plain TeX defines: @AA @AE @O @OE @L (plus lowercase versions) @ss.
\def\questiondown{?`}
\def\exclamdown{!`}
\def\ordf{\leavevmode\raise1ex\hbox{\switchtolllsize \underbar{a}}}
\def\ordm{\leavevmode\raise1ex\hbox{\switchtolllsize \underbar{o}}}
% Dotless i and dotless j, used for accents.
\def\imacro{i}
\def\jmacro{j}
\def\dotless#1{%
\def\temp{#1}%
\ifx\temp\imacro \ifmmode\imath \else\ptexi \fi
\else\ifx\temp\jmacro \ifmmode\jmath \else\j \fi
\else \errmessage{@dotless can be used only with i or j}%
\fi\fi
}
% The \TeX{} logo, as in plain, but resetting the spacing so that a
% period following counts as ending a sentence. (Idea found in latex.)
%
\edef\TeX{\TeX \spacefactor=1000 }
% @LaTeX{} logo. Not quite the same results as the definition in
% latex.ltx, since we use a different font for the raised A; it's most
% convenient for us to use an explicitly smaller font, rather than using
% the \scriptstyle font (since we don't reset \scriptstyle and
% \scriptscriptstyle).
%
\def\LaTeX{%
L\kern-.36em
{\setbox0=\hbox{T}%
\vbox to \ht0{\hbox{%
\ifx\textnominalsize\xwordpt
% for 10pt running text, lllsize (8pt) is too small for the A in LaTeX.
% Revert to plain's \scriptsize, which is 7pt.
\count255=\the\fam $\fam\count255 \scriptstyle A$%
\else
\ifx\curfontsize\smallword
% For footnotes and indices
\count255=\the\fam $\fam\count255 \scriptstyle A$%
\else
% For 11pt, we can use our lllsize.
\switchtolllsize A%
\fi
\fi
}%
\vss
}}%
\kern-.15em
\TeX
}
\def\smallword{small}
% Some math mode symbols. Define \ensuremath to switch into math mode
% unless we are already there. Expansion tricks may not be needed here,
% but safer, and can't hurt.
\def\ensuremath{\ifmmode \expandafter\asis \else\expandafter\ensuredmath \fi}
\def\ensuredmath#1{$\relax#1$}
%
\def\bullet{\ensuremath\ptexbullet}
\def\geq{\ensuremath\ge}
\def\leq{\ensuremath\le}
\def\minus{\ensuremath-}
% @dots{} outputs an ellipsis using the current font.
% We do .5em per period so that it has the same spacing in the cm
% typewriter fonts as three actual period characters; on the other hand,
% in other typewriter fonts three periods are wider than 1.5em. So do
% whichever is larger.
%
\def\dots{%
\leavevmode
\setbox0=\hbox{...}% get width of three periods
\ifdim\wd0 > 1.5em
\dimen0 = \wd0
\else
\dimen0 = 1.5em
\fi
\hbox to \dimen0{%
\hskip 0pt plus.25fil
.\hskip 0pt plus1fil
.\hskip 0pt plus1fil
.\hskip 0pt plus.5fil
}%
}
% @enddots{} is an end-of-sentence ellipsis.
%
\def\enddots{%
\dots
\spacefactor=\endofsentencespacefactor
}
% @point{}, @result{}, @expansion{}, @print{}, @equiv{}.
%
% Since these characters are used in examples, they should be an even number of
% \tt widths. Each \tt character is 1en, so two makes it 1em.
%
\def\point{$\star$}
\def\arrow{\leavevmode\raise.05ex\hbox to 1em{\hfil$\rightarrow$\hfil}}
\def\result{\leavevmode\raise.05ex\hbox to 1em{\hfil$\Rightarrow$\hfil}}
\def\expansion{\leavevmode\hbox to 1em{\hfil$\mapsto$\hfil}}
\def\print{\leavevmode\lower.1ex\hbox to 1em{\hfil$\dashv$\hfil}}
\def\equiv{\leavevmode\hbox to 1em{\hfil$\ptexequiv$\hfil}}
% The @error{} command.
% Adapted from the TeXbook's \boxit.
%
\newbox\errorbox
%
{\ttfont \global\dimen0 = 3em}% Width of the box.
\dimen2 = .55pt % Thickness of rules
% The text. (`r' is open on the right, `e' somewhat less so on the left.)
\setbox0 = \hbox{\kern-.75pt \reducedsf \putworderror\kern-1.5pt}
%
\setbox\errorbox=\hbox to \dimen0{\hfil
\hsize = \dimen0 \advance\hsize by -5.8pt % Space to left+right.
\advance\hsize by -2\dimen2 % Rules.
\vbox{%
\hrule height\dimen2
\hbox{\vrule width\dimen2 \kern3pt % Space to left of text.
\vtop{\kern2.4pt \box0 \kern2.4pt}% Space above/below.
\kern3pt\vrule width\dimen2}% Space to right.
\hrule height\dimen2}
\hfil}
%
\def\error{\leavevmode\lower.7ex\copy\errorbox}
% @pounds{} is a sterling sign, which Knuth put in the CM italic font.
%
\def\pounds{{\ifusingtt{\ecfont\char"BF}{\it\$}}}
% @euro{} comes from a separate font, depending on the current style.
% We use the free feym* fonts from the eurosym package by Henrik
% Theiling, which support regular, slanted, bold and bold slanted (and
% "outlined" (blackboard board, sort of) versions, which we don't need).
% It is available from http://www.ctan.org/tex-archive/fonts/eurosym.
%
% Although only regular is the truly official Euro symbol, we ignore
% that. The Euro is designed to be slightly taller than the regular
% font height.
%
% feymr - regular
% feymo - slanted
% feybr - bold
% feybo - bold slanted
%
% There is no good (free) typewriter version, to my knowledge.
% A feymr10 euro is ~7.3pt wide, while a normal cmtt10 char is ~5.25pt wide.
% Hmm.
%
% Also doesn't work in math. Do we need to do math with euro symbols?
% Hope not.
%
%
\def\euro{{\eurofont e}}
\def\eurofont{%
% We set the font at each command, rather than predefining it in
% \textfonts and the other font-switching commands, so that
% installations which never need the symbol don't have to have the
% font installed.
%
% There is only one designed size (nominal 10pt), so we always scale
% that to the current nominal size.
%
% By the way, simply using "at 1em" works for cmr10 and the like, but
% does not work for cmbx10 and other extended/shrunken fonts.
%
\def\eurosize{\csname\curfontsize nominalsize\endcsname}%
%
\ifx\curfontstyle\bfstylename
% bold:
\font\thiseurofont = \ifusingit{feybo10}{feybr10} at \eurosize
\else
% regular:
\font\thiseurofont = \ifusingit{feymo10}{feymr10} at \eurosize
\fi
\thiseurofont
}
% Glyphs from the EC fonts. We don't use \let for the aliases, because
% sometimes we redefine the original macro, and the alias should reflect
% the redefinition.
%
% Use LaTeX names for the Icelandic letters.
\def\DH{{\ecfont \char"D0}} % Eth
\def\dh{{\ecfont \char"F0}} % eth
\def\TH{{\ecfont \char"DE}} % Thorn
\def\th{{\ecfont \char"FE}} % thorn
%
\def\guillemetleft{{\ecfont \char"13}}
\def\guillemotleft{\guillemetleft}
\def\guillemetright{{\ecfont \char"14}}
\def\guillemotright{\guillemetright}
\def\guilsinglleft{{\ecfont \char"0E}}
\def\guilsinglright{{\ecfont \char"0F}}
\def\quotedblbase{{\ecfont \char"12}}
\def\quotesinglbase{{\ecfont \char"0D}}
%
\def\L{{\ecfont \char"8A}} % L with stroke
\def\l{{\ecfont \char"AA}} % l with stroke
%
% This positioning is not perfect (see the ogonek LaTeX package), but
% we have the precomposed glyphs for the most common cases. We put the
% tests to use those glyphs in the single \ogonek macro so we have fewer
% dummy definitions to worry about for index entries, etc.
%
% ogonek is also used with other letters in Lithuanian (IOU), but using
% the precomposed glyphs for those is not so easy since they aren't in
% the same EC font.
\def\ogonek#1{{%
\def\temp{#1}%
\ifx\temp\macrocharA\Aogonek
\else\ifx\temp\macrochara\aogonek
\else\ifx\temp\macrocharE\Eogonek
\else\ifx\temp\macrochare\eogonek
\else
\ecfont \setbox0=\hbox{#1}%
\ifdim\ht0=1ex\accent"0C #1%
\else\ooalign{\unhbox0\crcr\hidewidth\char"0C \hidewidth}%
\fi
\fi\fi\fi\fi
}%
}
\def\Aogonek{{\ecfont \char"81}}\def\macrocharA{A}
\def\aogonek{{\ecfont \char"A1}}\def\macrochara{a}
\def\Eogonek{{\ecfont \char"86}}\def\macrocharE{E}
\def\eogonek{{\ecfont \char"A6}}\def\macrochare{e}
%
% Use the European Computer Modern fonts (cm-super in outline format)
% for non-CM glyphs. That is ec* for regular text and tc* for the text
% companion symbols (LaTeX TS1 encoding). Both are part of the ec
% package and follow the same conventions.
%
\def\ecfont{\etcfont{e}}
\def\tcfont{\etcfont{t}}
%
\def\etcfont#1{%
% We can't distinguish serif/sans and italic/slanted, but this
% is used for crude hacks anyway (like adding French and German
% quotes to documents typeset with CM, where we lose kerning), so
% hopefully nobody will notice/care.
\edef\ecsize{\csname\curfontsize ecsize\endcsname}%
\edef\nominalsize{\csname\curfontsize nominalsize\endcsname}%
\ifusingtt
% typewriter:
{\font\thisecfont = #1ctt\ecsize \space at \nominalsize}%
% else
{\ifx\curfontstyle\bfstylename
% bold:
\font\thisecfont = #1cb\ifusingit{i}{x}\ecsize \space at \nominalsize
\else
% regular:
\font\thisecfont = #1c\ifusingit{ti}{rm}\ecsize \space at \nominalsize
\fi}%
\thisecfont
}
% @registeredsymbol - R in a circle. The font for the R should really
% be smaller yet, but lllsize is the best we can do for now.
% Adapted from the plain.tex definition of \copyright.
%
\def\registeredsymbol{%
$^{{\ooalign{\hfil\raise.07ex\hbox{\switchtolllsize R}%
\hfil\crcr\Orb}}%
}$%
}
% @textdegree - the normal degrees sign.
%
\def\textdegree{%
\ifmmode ^\circ
\else {\tcfont \char 176}%
\fi}
% Laurent Siebenmann reports \Orb undefined with:
% Textures 1.7.7 (preloaded format=plain 93.10.14) (68K) 16 APR 2004 02:38
% so we'll define it if necessary.
%
\ifx\Orb\thisisundefined
\def\Orb{\mathhexbox20D}
\fi
% Quotes.
\chardef\quoteleft=`\`
\chardef\quoteright=`\'
% only change font for tt for correct kerning and to avoid using
% \ecfont unless necessary.
\def\quotedblleft{%
\ifusingtt{{\ecfont\char"10}}{{\char"5C}}%
}
\def\quotedblright{%
\ifusingtt{{\ecfont\char"11}}{{\char`\"}}%
}
\message{page headings,}
\newskip\titlepagetopglue \titlepagetopglue = 1.5in
\newskip\titlepagebottomglue \titlepagebottomglue = 2pc
% First the title page. Must do @settitle before @titlepage.
\newif\ifseenauthor
\newif\iffinishedtitlepage
% @setcontentsaftertitlepage used to do an implicit @contents or
% @shortcontents after @end titlepage, but it is now obsolete.
\def\setcontentsaftertitlepage{%
\errmessage{@setcontentsaftertitlepage has been removed as a Texinfo
command; move your @contents command if you want the contents
after the title page.}}%
\def\setshortcontentsaftertitlepage{%
\errmessage{@setshortcontentsaftertitlepage has been removed as a Texinfo
command; move your @shortcontents and @contents commands if you
want the contents after the title page.}}%
\parseargdef\shorttitlepage{%
{\headingsoff \begingroup \hbox{}\vskip 1.5in \chaprm \centerline{#1}%
\endgroup\page\hbox{}\page}\pageone}
\envdef\titlepage{%
% Open one extra group, as we want to close it in the middle of \Etitlepage.
\begingroup
\parindent=0pt \textfonts
\headingsoff
% Leave some space at the very top of the page.
\vglue\titlepagetopglue
% No rule at page bottom unless we print one at the top with @title.
\finishedtitlepagetrue
%
% Most title ``pages'' are actually two pages long, with space
% at the top of the second. We don't want the ragged left on the second.
\let\oldpage = \page
\def\page{%
\iffinishedtitlepage\else
\finishtitlepage
\fi
\let\page = \oldpage
\page
\null
}%
}
\def\Etitlepage{%
\iffinishedtitlepage\else
\finishtitlepage
\fi
% It is important to do the page break before ending the group,
% because the headline and footline are only empty inside the group.
% If we use the new definition of \page, we always get a blank page
% after the title page, which we certainly don't want.
\oldpage
\pageone
\endgroup
%
}
\def\finishtitlepage{%
\vskip4pt \hrule height 2pt width \hsize
\vskip\titlepagebottomglue
\finishedtitlepagetrue
}
% Settings used for typesetting titles: no hyphenation, no indentation,
% don't worry much about spacing, ragged right. This should be used
% inside a \vbox, and fonts need to be set appropriately first. \par should
% be specified before the end of the \vbox, since a vbox is a group.
%
\def\raggedtitlesettings{%
\rm
\hyphenpenalty=10000
\parindent=0pt
\tolerance=5000
\ptexraggedright
}
% Macros to be used within @titlepage:
\let\subtitlerm=\rmfont
\def\subtitlefont{\subtitlerm \normalbaselineskip = 13pt \normalbaselines}
\parseargdef\title{%
\checkenv\titlepage
\vbox{\titlefonts \raggedtitlesettings #1\par}%
% print a rule at the page bottom also.
\finishedtitlepagefalse
\vskip4pt \hrule height 4pt width \hsize \vskip4pt
}
\parseargdef\subtitle{%
\checkenv\titlepage
{\subtitlefont \rightline{#1}}%
}
% @author should come last, but may come many times.
% It can also be used inside @quotation.
%
\parseargdef\author{%
\def\temp{\quotation}%
\ifx\thisenv\temp
\def\quotationauthor{#1}% printed in \Equotation.
\else
\checkenv\titlepage
\ifseenauthor\else \vskip 0pt plus 1filll \seenauthortrue \fi
{\secfonts\rm \leftline{#1}}%
\fi
}
% Set up page headings and footings.
\let\thispage=\folio
\newtoks\evenheadline % headline on even pages
\newtoks\oddheadline % headline on odd pages
\newtoks\evenchapheadline% headline on even pages with a new chapter
\newtoks\oddchapheadline % headline on odd pages with a new chapter
\newtoks\evenfootline % footline on even pages
\newtoks\oddfootline % footline on odd pages
% Now make \makeheadline and \makefootline in Plain TeX use those variables
\headline={{\textfonts\rm\frenchspacingsetting
\ifchapterpage
\ifodd\pageno\the\oddchapheadline\else\the\evenchapheadline\fi
\else
\ifodd\pageno\the\oddheadline\else\the\evenheadline\fi
\fi}}
\footline={{\textfonts\rm\frenchspacingsetting
\ifodd\pageno \the\oddfootline \else \the\evenfootline \fi}%
\HEADINGShook}
\let\HEADINGShook=\relax
% Commands to set those variables.
% For example, this is what @headings on does
% @evenheading @thistitle|@thispage|@thischapter
% @oddheading @thischapter|@thispage|@thistitle
% @evenfooting @thisfile||
% @oddfooting ||@thisfile
\def\evenheading{\parsearg\evenheadingxxx}
\def\evenheadingxxx #1{\evenheadingyyy #1\|\|\|\|\finish}
\def\evenheadingyyy #1\|#2\|#3\|#4\finish{%
\global\evenheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}
\global\evenchapheadline=\evenheadline}
\def\oddheading{\parsearg\oddheadingxxx}
\def\oddheadingxxx #1{\oddheadingyyy #1\|\|\|\|\finish}
\def\oddheadingyyy #1\|#2\|#3\|#4\finish{%
\global\oddheadline={\rlap{\centerline{#2}}\line{#1\hfil#3}}%
\global\oddchapheadline=\oddheadline}
\parseargdef\everyheading{\oddheadingxxx{#1}\evenheadingxxx{#1}}%
\def\evenfooting{\parsearg\evenfootingxxx}
\def\evenfootingxxx #1{\evenfootingyyy #1\|\|\|\|\finish}
\def\evenfootingyyy #1\|#2\|#3\|#4\finish{%
\global\evenfootline={\rlap{\centerline{#2}}\line{#1\hfil#3}}}
\def\oddfooting{\parsearg\oddfootingxxx}
\def\oddfootingxxx #1{\oddfootingyyy #1\|\|\|\|\finish}
\def\oddfootingyyy #1\|#2\|#3\|#4\finish{%
\global\oddfootline = {\rlap{\centerline{#2}}\line{#1\hfil#3}}%
%
% Leave some space for the footline. Hopefully ok to assume
% @evenfooting will not be used by itself.
\global\advance\txipageheight by -12pt
\global\advance\vsize by -12pt
}
\parseargdef\everyfooting{\oddfootingxxx{#1}\evenfootingxxx{#1}}
% @evenheadingmarks top \thischapter <- chapter at the top of a page
% @evenheadingmarks bottom \thischapter <- chapter at the bottom of a page
%
% The same set of arguments for:
%
% @oddheadingmarks
% @evenfootingmarks
% @oddfootingmarks
% @everyheadingmarks
% @everyfootingmarks
% These define \getoddheadingmarks, \getevenheadingmarks,
% \getoddfootingmarks, and \getevenfootingmarks, each to one of
% \gettopheadingmarks, \getbottomheadingmarks.
%
\def\evenheadingmarks{\headingmarks{even}{heading}}
\def\oddheadingmarks{\headingmarks{odd}{heading}}
\def\evenfootingmarks{\headingmarks{even}{footing}}
\def\oddfootingmarks{\headingmarks{odd}{footing}}
\parseargdef\everyheadingmarks{\headingmarks{even}{heading}{#1}
\headingmarks{odd}{heading}{#1} }
\parseargdef\everyfootingmarks{\headingmarks{even}{footing}{#1}
\headingmarks{odd}{footing}{#1} }
% #1 = even/odd, #2 = heading/footing, #3 = top/bottom.
\def\headingmarks#1#2#3 {%
\expandafter\let\expandafter\temp \csname get#3headingmarks\endcsname
\global\expandafter\let\csname get#1#2marks\endcsname \temp
}
\everyheadingmarks bottom
\everyfootingmarks bottom
% @headings double turns headings on for double-sided printing.
% @headings single turns headings on for single-sided printing.
% @headings off turns them off.
% @headings on same as @headings double, retained for compatibility.
% @headings after turns on double-sided headings after this page.
% @headings doubleafter turns on double-sided headings after this page.
% @headings singleafter turns on single-sided headings after this page.
% By default, they are off at the start of a document,
% and turned `on' after @end titlepage.
\parseargdef\headings{\csname HEADINGS#1\endcsname}
\def\headingsoff{% non-global headings elimination
\evenheadline={\hfil}\evenfootline={\hfil}\evenchapheadline={\hfil}%
\oddheadline={\hfil}\oddfootline={\hfil}\oddchapheadline={\hfil}%
}
\def\HEADINGSoff{{\globaldefs=1 \headingsoff}} % global setting
% Set the page number to 1.
\def\pageone{
\global\pageno=1
\global\arabiccount = \pagecount
}
\let\contentsalignmacro = \chappager
% \def\HEADINGSon{\HEADINGSdouble} % defined by \CHAPPAGon
% For double-sided printing, put current file name in lower left corner,
% chapter name on inside top of right hand pages, document
% title on inside top of left hand pages, and page numbers on outside top
% edge of all pages.
\def\HEADINGSafter{\let\HEADINGShook=\HEADINGSdouble}
\let\HEADINGSdoubleafter=\HEADINGSafter
\def\HEADINGSdouble{%
\global\evenfootline={\hfil}
\global\oddfootline={\hfil}
\global\evenheadline={\line{\folio\hfil\thistitle}}
\global\oddheadline={\line{\thischapter\hfil\folio}}
\global\evenchapheadline={\line{\folio\hfil\thistitle}}
\global\oddchapheadline={\line{\hfil\folio}}
\global\let\contentsalignmacro = \chapoddpage
}
% For single-sided printing, chapter title goes across top left of page,
% page number on top right.
\def\HEADINGSsingleafter{\let\HEADINGShook=\HEADINGSsingle}
\def\HEADINGSsingle{%
\global\evenfootline={\hfil}
\global\oddfootline={\hfil}
\global\evenheadline={\line{\thischapter\hfil\folio}}
\global\oddheadline={\line{\thischapter\hfil\folio}}
\global\evenchapheadline={\line{\hfil\folio}}
\global\oddchapheadline={\line{\hfil\folio}}
\global\let\contentsalignmacro = \chappager
}
% for @setchapternewpage off
\def\HEADINGSsinglechapoff{%
\global\evenfootline={\hfil}
\global\oddfootline={\hfil}
\global\evenheadline={\line{\thischapter\hfil\folio}}
\global\oddheadline={\line{\thischapter\hfil\folio}}
\global\evenchapheadline=\evenheadline
\global\oddchapheadline=\oddheadline
\global\let\contentsalignmacro = \chappager
}
% Subroutines used in generating headings
% This produces Day Month Year style of output.
% Only define if not already defined, in case a txi-??.tex file has set
% up a different format (e.g., txi-cs.tex does this).
\ifx\today\thisisundefined
\def\today{%
\number\day\space
\ifcase\month
\or\putwordMJan\or\putwordMFeb\or\putwordMMar\or\putwordMApr
\or\putwordMMay\or\putwordMJun\or\putwordMJul\or\putwordMAug
\or\putwordMSep\or\putwordMOct\or\putwordMNov\or\putwordMDec
\fi
\space\number\year}
\fi
% @settitle line... specifies the title of the document, for headings.
% It generates no output of its own.
\def\thistitle{\putwordNoTitle}
\def\settitle{\parsearg{\gdef\thistitle}}
\message{tables,}
% Tables -- @table, @ftable, @vtable, @item(x).
% default indentation of table text
\newdimen\tableindent \tableindent=.8in
% default indentation of @itemize and @enumerate text
\newdimen\itemindent \itemindent=.3in
% margin between end of table item and start of table text.
\newdimen\itemmargin \itemmargin=.1in
% used internally for \itemindent minus \itemmargin
\newdimen\itemmax
% Note @table, @ftable, and @vtable define @item, @itemx, etc., with
% these defs.
% They also define \itemindex
% to index the item name in whatever manner is desired (perhaps none).
\newif\ifitemxneedsnegativevskip
\def\itemxpar{\par\ifitemxneedsnegativevskip\nobreak\vskip-\parskip\nobreak\fi}
\def\internalBitem{\smallbreak \parsearg\itemzzz}
\def\internalBitemx{\itemxpar \parsearg\itemzzz}
\def\itemzzz #1{\begingroup %
\advance\hsize by -\rightskip
\advance\hsize by -\tableindent
\setbox0=\hbox{\itemindicate{#1}}%
\itemindex{#1}%
\nobreak % This prevents a break before @itemx.
%
% If the item text does not fit in the space we have, put it on a line
% by itself, and do not allow a page break either before or after that
% line. We do not start a paragraph here because then if the next
% command is, e.g., @kindex, the whatsit would get put into the
% horizontal list on a line by itself, resulting in extra blank space.
\ifdim \wd0>\itemmax
%
% Make this a paragraph so we get the \parskip glue and wrapping,
% but leave it ragged-right.
\begingroup
\advance\leftskip by-\tableindent
\advance\hsize by\tableindent
\advance\rightskip by0pt plus1fil\relax
\leavevmode\unhbox0\par
\endgroup
%
% We're going to be starting a paragraph, but we don't want the
% \parskip glue -- logically it's part of the @item we just started.
\nobreak \vskip-\parskip
%
% Stop a page break at the \parskip glue coming up. However, if
% what follows is an environment such as @example, there will be no
% \parskip glue; then the negative vskip we just inserted would
% cause the example and the item to crash together. So we use this
% bizarre value of 10001 as a signal to \aboveenvbreak to insert
% \parskip glue after all. Section titles are handled this way also.
%
\penalty 10001
\endgroup
\itemxneedsnegativevskipfalse
\else
% The item text fits into the space. Start a paragraph, so that the
% following text (if any) will end up on the same line.
\noindent
% Do this with kerns and \unhbox so that if there is a footnote in
% the item text, it can migrate to the main vertical list and
% eventually be printed.
\nobreak\kern-\tableindent
\dimen0 = \itemmax \advance\dimen0 by \itemmargin \advance\dimen0 by -\wd0
\unhbox0
\nobreak\kern\dimen0
\endgroup
\itemxneedsnegativevskiptrue
\fi
}
\def\item{\errmessage{@item while not in a list environment}}
\def\itemx{\errmessage{@itemx while not in a list environment}}
% @table, @ftable, @vtable.
\envdef\table{%
\let\itemindex\gobble
\tablecheck{table}%
}
\envdef\ftable{%
\def\itemindex ##1{\doind {fn}{\code{##1}}}%
\tablecheck{ftable}%
}
\envdef\vtable{%
\def\itemindex ##1{\doind {vr}{\code{##1}}}%
\tablecheck{vtable}%
}
\def\tablecheck#1{%
\ifnum \the\catcode`\^^M=\active
\endgroup
\errmessage{This command won't work in this context; perhaps the problem is
that we are \inenvironment\thisenv}%
\def\next{\doignore{#1}}%
\else
\let\next\tablex
\fi
\next
}
\def\tablex#1{%
\def\itemindicate{#1}%
\parsearg\tabley
}
\def\tabley#1{%
{%
\makevalueexpandable
\edef\temp{\noexpand\tablez #1\space\space\space}%
\expandafter
}\temp \endtablez
}
\def\tablez #1 #2 #3 #4\endtablez{%
\aboveenvbreak
\ifnum 0#1>0 \advance \leftskip by #1\mil \fi
\ifnum 0#2>0 \tableindent=#2\mil \fi
\ifnum 0#3>0 \advance \rightskip by #3\mil \fi
\itemmax=\tableindent
\advance \itemmax by -\itemmargin
\advance \leftskip by \tableindent
\exdentamount=\tableindent
\parindent = 0pt
\parskip = \smallskipamount
\ifdim \parskip=0pt \parskip=2pt \fi
\let\item = \internalBitem
\let\itemx = \internalBitemx
}
\def\Etable{\endgraf\afterenvbreak}
\let\Eftable\Etable
\let\Evtable\Etable
\let\Eitemize\Etable
\let\Eenumerate\Etable
% This is the counter used by @enumerate, which is really @itemize
\newcount \itemno
\envdef\itemize{\parsearg\doitemize}
\def\doitemize#1{%
\aboveenvbreak
\itemmax=\itemindent
\advance\itemmax by -\itemmargin
\advance\leftskip by \itemindent
\exdentamount=\itemindent
\parindent=0pt
\parskip=\smallskipamount
\ifdim\parskip=0pt \parskip=2pt \fi
%
% Try typesetting the item mark so that if the document erroneously says
% something like @itemize @samp (intending @table), there's an error
% right away at the @itemize. It's not the best error message in the
% world, but it's better than leaving it to the @item. This means if
% the user wants an empty mark, they have to say @w{} not just @w.
\def\itemcontents{#1}%
\setbox0 = \hbox{\itemcontents}%
%
% @itemize with no arg is equivalent to @itemize @bullet.
\ifx\itemcontents\empty\def\itemcontents{\bullet}\fi
%
\let\item=\itemizeitem
}
% Definition of @item while inside @itemize and @enumerate.
%
\def\itemizeitem{%
\advance\itemno by 1 % for enumerations
{\let\par=\endgraf \smallbreak}% reasonable place to break
{%
% If the document has an @itemize directly after a section title, a
% \nobreak will be last on the list, and \sectionheading will have
% done a \vskip-\parskip. In that case, we don't want to zero
% parskip, or the item text will crash with the heading. On the
% other hand, when there is normal text preceding the item (as there
% usually is), we do want to zero parskip, or there would be too much
% space. In that case, we won't have a \nobreak before. At least
% that's the theory.
\ifnum\lastpenalty<10000 \parskip=0in \fi
\noindent
\hbox to 0pt{\hss \itemcontents \kern\itemmargin}%
%
\ifinner\else
\vadjust{\penalty 1200}% not good to break after first line of item.
\fi
% We can be in inner vertical mode in a footnote, although an
% @itemize looks awful there.
}%
\flushcr
}
% \splitoff TOKENS\endmark defines \first to be the first token in
% TOKENS, and \rest to be the remainder.
%
\def\splitoff#1#2\endmark{\def\first{#1}\def\rest{#2}}%
% Allow an optional argument of an uppercase letter, lowercase letter,
% or number, to specify the first label in the enumerated list. No
% argument is the same as `1'.
%
\envparseargdef\enumerate{\enumeratey #1 \endenumeratey}
\def\enumeratey #1 #2\endenumeratey{%
% If we were given no argument, pretend we were given `1'.
\def\thearg{#1}%
\ifx\thearg\empty \def\thearg{1}\fi
%
% Detect if the argument is a single token. If so, it might be a
% letter. Otherwise, the only valid thing it can be is a number.
% (We will always have one token, because of the test we just made.
% This is a good thing, since \splitoff doesn't work given nothing at
% all -- the first parameter is undelimited.)
\expandafter\splitoff\thearg\endmark
\ifx\rest\empty
% Only one token in the argument. It could still be anything.
% A ``lowercase letter'' is one whose \lccode is nonzero.
% An ``uppercase letter'' is one whose \lccode is both nonzero, and
% not equal to itself.
% Otherwise, we assume it's a number.
%
% We need the \relax at the end of the \ifnum lines to stop TeX from
% continuing to look for a .
%
\ifnum\lccode\expandafter`\thearg=0\relax
\numericenumerate % a number (we hope)
\else
% It's a letter.
\ifnum\lccode\expandafter`\thearg=\expandafter`\thearg\relax
\lowercaseenumerate % lowercase letter
\else
\uppercaseenumerate % uppercase letter
\fi
\fi
\else
% Multiple tokens in the argument. We hope it's a number.
\numericenumerate
\fi
}
% An @enumerate whose labels are integers. The starting integer is
% given in \thearg.
%
\def\numericenumerate{%
\itemno = \thearg
\startenumeration{\the\itemno}%
}
% The starting (lowercase) letter is in \thearg.
\def\lowercaseenumerate{%
\itemno = \expandafter`\thearg
\startenumeration{%
% Be sure we're not beyond the end of the alphabet.
\ifnum\itemno=0
\errmessage{No more lowercase letters in @enumerate; get a bigger
alphabet}%
\fi
\char\lccode\itemno
}%
}
% The starting (uppercase) letter is in \thearg.
\def\uppercaseenumerate{%
\itemno = \expandafter`\thearg
\startenumeration{%
% Be sure we're not beyond the end of the alphabet.
\ifnum\itemno=0
\errmessage{No more uppercase letters in @enumerate; get a bigger
alphabet}
\fi
\char\uccode\itemno
}%
}
% Call \doitemize, adding a period to the first argument and supplying the
% common last two arguments. Also subtract one from the initial value in
% \itemno, since @item increments \itemno.
%
\def\startenumeration#1{%
\advance\itemno by -1
\doitemize{#1.}\flushcr
}
% @multitable macros
% Macros used to set up halign preamble:
%
\let\endsetuptable\relax
\def\xendsetuptable{\endsetuptable}
\let\columnfractions\relax
\def\xcolumnfractions{\columnfractions}
\newif\ifsetpercent
% #1 is the @columnfraction, usually a decimal number like .5, but might
% be just 1. We just use it, whatever it is.
%
\def\pickupwholefraction#1 {%
\global\advance\colcount by 1
\expandafter\xdef\csname col\the\colcount\endcsname{#1\hsize}%
\setuptable
}
\newcount\colcount
\def\setuptable#1{%
\def\firstarg{#1}%
\ifx\firstarg\xendsetuptable
\let\go = \relax
\else
\ifx\firstarg\xcolumnfractions
\global\setpercenttrue
\else
\ifsetpercent
\let\go\pickupwholefraction
\else
\global\advance\colcount by 1
\setbox0=\hbox{#1\unskip\space}% Add a normal word space as a
% separator; typically that is always in the input, anyway.
\expandafter\xdef\csname col\the\colcount\endcsname{\the\wd0}%
\fi
\fi
\ifx\go\pickupwholefraction
% Put the argument back for the \pickupwholefraction call, so
% we'll always have a period there to be parsed.
\def\go{\pickupwholefraction#1}%
\else
\let\go = \setuptable
\fi%
\fi
\go
}
% @headitem starts a heading row, which we typeset in bold. Assignments
% have to be global since we are inside the implicit group of an
% alignment entry. \everycr below resets \everytab so we don't have to
% undo it ourselves.
\def\headitemfont{\b}% for people to use in the template row; not changeable
\def\headitem{%
\crcr % must appear first
\gdef\headitemcrhook{\nobreak}% attempt to avoid page break after headings
\global\everytab={\bf}% can't use \headitemfont since the parsing differs
\the\everytab % for the first item
}%
%
% default for tables with no headings.
\let\headitemcrhook=\relax
%
\def\tab{\checkenv\multitable &\the\everytab}%
\newtoks\everytab % insert after every tab.
%
\envdef\multitable{%
\vskip\parskip
\startsavinginserts
%
% @item within a multitable starts a normal row.
% We use \def instead of \let so that if one of the multitable entries
% contains an @itemize, we don't choke on the \item (seen as \crcr aka
% \endtemplate) expanding \doitemize.
\def\item{\crcr}%
%
\tolerance=9500
\hbadness=9500
\parskip=0pt
\parindent=6pt
\overfullrule=0pt
\global\colcount=0
%
\everycr = {%
\noalign{%
\global\everytab={}% Reset from possible headitem.
\global\colcount=0 % Reset the column counter.
%
% Check for saved footnotes, etc.:
\checkinserts
%
% Perhaps a \nobreak, then reset:
\headitemcrhook
\global\let\headitemcrhook=\relax
}%
}%
%
\parsearg\domultitable
}
\def\domultitable#1{%
% To parse everything between @multitable and @item:
\setuptable#1 \endsetuptable
%
% This preamble sets up a generic column definition, which will
% be used as many times as user calls for columns.
% \vtop will set a single line and will also let text wrap and
% continue for many paragraphs if desired.
\halign\bgroup &%
\global\advance\colcount by 1
\strut
\vtop{%
\advance\hsize by -1\leftskip
% Find the correct column width
\hsize=\expandafter\csname col\the\colcount\endcsname
%
\advance\rightskip by -1\rightskip % Zero leaving only any stretch
\ifnum\colcount=1
\advance\hsize by\leftskip % Add indent of surrounding text
\else
% In order to keep entries from bumping into each other.
\leftskip=12pt
\ifsetpercent \else
% If a template has been used
\advance\hsize by \leftskip
\fi
\fi
\noindent\ignorespaces##\unskip\strut
}\cr
}
\def\Emultitable{%
\crcr
\egroup % end the \halign
\global\setpercentfalse
}
\message{conditionals,}
% @iftex, @ifnotdocbook, @ifnothtml, @ifnotinfo, @ifnotlatex, @ifnotplaintext,
% @ifnotxml always succeed. They currently do nothing; we don't
% attempt to check whether the conditionals are properly nested. But we
% have to remember that they are conditionals, so that @end doesn't
% attempt to close an environment group.
%
\def\makecond#1{%
\expandafter\let\csname #1\endcsname = \relax
\expandafter\let\csname iscond.#1\endcsname = 1
}
\makecond{iftex}
\makecond{ifnotdocbook}
\makecond{ifnothtml}
\makecond{ifnotinfo}
\makecond{ifnotlatex}
\makecond{ifnotplaintext}
\makecond{ifnotxml}
% Ignore @ignore, @ifhtml, @ifinfo, and the like.
%
\def\direntry{\doignore{direntry}}
\def\documentdescription{\doignore{documentdescription}}
\def\docbook{\doignore{docbook}}
\def\html{\doignore{html}}
\def\ifdocbook{\doignore{ifdocbook}}
\def\ifhtml{\doignore{ifhtml}}
\def\ifinfo{\doignore{ifinfo}}
\def\iflatex{\doignore{iflatex}}
\def\ifnottex{\doignore{ifnottex}}
\def\ifplaintext{\doignore{ifplaintext}}
\def\ifxml{\doignore{ifxml}}
\def\ignore{\doignore{ignore}}
\def\latex{\doignore{latex}}
\def\menu{\doignore{menu}}
\def\xml{\doignore{xml}}
% Ignore text until a line `@end #1', keeping track of nested conditionals.
%
% A count to remember the depth of nesting.
\newcount\doignorecount
\def\doignore#1{\begingroup
% Scan in ``verbatim'' mode:
\obeylines
\catcode`\@ = \other
\catcode`\{ = \other
\catcode`\} = \other
%
% Make sure that spaces turn into tokens that match what \doignoretext wants.
\spaceisspace
%
% Count number of #1's that we've seen.
\doignorecount = 0
%
% Swallow text until we reach the matching `@end #1'.
\dodoignore{#1}%
}
{ \catcode`_=11 % We want to use \_STOP_ which cannot appear in texinfo source.
\obeylines %
%
\gdef\dodoignore#1{%
% #1 contains the command name as a string, e.g., `ifinfo'.
%
% Define a command to find the next `@end #1'.
\long\def\doignoretext##1^^M@end #1{%
\doignoretextyyy##1^^M@#1\_STOP_}%
%
% And this command to find another #1 command, at the beginning of a
% line. (Otherwise, we would consider a line `@c @ifset', for
% example, to count as an @ifset for nesting.)
\long\def\doignoretextyyy##1^^M@#1##2\_STOP_{\doignoreyyy{##2}\_STOP_}%
%
% And now expand that command.
\doignoretext ^^M%
}%
}
\def\doignoreyyy#1{%
\def\temp{#1}%
\ifx\temp\empty % Nothing found.
\let\next\doignoretextzzz
\else % Found a nested condition, ...
\advance\doignorecount by 1
\let\next\doignoretextyyy % ..., look for another.
% If we're here, #1 ends with ^^M\ifinfo (for example).
\fi
\next #1% the token \_STOP_ is present just after this macro.
}
% We have to swallow the remaining "\_STOP_".
%
\def\doignoretextzzz#1{%
\ifnum\doignorecount = 0 % We have just found the outermost @end.
\let\next\enddoignore
\else % Still inside a nested condition.
\advance\doignorecount by -1
\let\next\doignoretext % Look for the next @end.
\fi
\next
}
% Finish off ignored text.
{ \obeylines%
% Ignore anything after the last `@end #1'; this matters in verbatim
% environments, where otherwise the newline after an ignored conditional
% would result in a blank line in the output.
\gdef\enddoignore#1^^M{\endgroup\ignorespaces}%
}
% @set VAR sets the variable VAR to an empty value.
% @set VAR REST-OF-LINE sets VAR to the value REST-OF-LINE.
%
% Since we want to separate VAR from REST-OF-LINE (which might be
% empty), we can't just use \parsearg; we have to insert a space of our
% own to delimit the rest of the line, and then take it out again if we
% didn't need it.
% We rely on the fact that \parsearg sets \catcode`\ =10.
%
\parseargdef\set{\setyyy#1 \endsetyyy}
\def\setyyy#1 #2\endsetyyy{%
{%
\makevalueexpandable
\def\temp{#2}%
\edef\next{\gdef\makecsname{SET#1}}%
\ifx\temp\empty
\next{}%
\else
\setzzz#2\endsetzzz
\fi
}%
}
% Remove the trailing space \setxxx inserted.
\def\setzzz#1 \endsetzzz{\next{#1}}
% @clear VAR clears (i.e., unsets) the variable VAR.
%
\parseargdef\clear{%
{%
\makevalueexpandable
\global\expandafter\let\csname SET#1\endcsname=\relax
}%
}
% @value{foo} gets the text saved in variable foo.
\def\value{\begingroup\makevalueexpandable\valuexxx}
\def\valuexxx#1{\expandablevalue{#1}\endgroup}
{
\catcode`\-=\active \catcode`\_=\active
%
\gdef\makevalueexpandable{%
\let\value = \expandablevalue
% We don't want these characters active, ...
\catcode`\-=\other \catcode`\_=\other
% ..., but we might end up with active ones in the argument if
% we're called from @code, as @code{@value{foo-bar_}}, though.
% So \let them to their normal equivalents.
\let-\normaldash \let_\normalunderscore
}
}
\def\expandablevalue#1{%
\expandafter\ifx\csname SET#1\endcsname\relax
{[No value for ``#1'']}%
\message{Variable `#1', used in @value, is not set.}%
\else
\csname SET#1\endcsname
\fi
}
% Like \expandablevalue, but completely expandable (the \message in the
% definition above operates at the execution level of TeX). Used when
% writing to auxiliary files, due to the expansion that \write does.
% If flag is undefined, pass through an unexpanded @value command: maybe it
% will be set by the time it is read back in.
%
% NB flag names containing - or _ may not work here.
\def\dummyvalue#1{%
\expandafter\ifx\csname SET#1\endcsname\relax
\string\value{#1}%
\else
\csname SET#1\endcsname
\fi
}
% Used for @value's in index entries to form the sort key: expand the @value
% if possible, otherwise sort late.
\def\indexnofontsvalue#1{%
\expandafter\ifx\csname SET#1\endcsname\relax
ZZZZZZZ%
\else
\csname SET#1\endcsname
\fi
}
% @ifset VAR ... @end ifset reads the `...' iff VAR has been defined
% with @set.
%
% To get the special treatment we need for `@end ifset,' we call
% \makecond and then redefine.
%
\makecond{ifset}
\def\ifset{\parsearg{\doifset{\let\next=\ifsetfail}}}
\def\doifset#1#2{%
{%
\makevalueexpandable
\let\next=\empty
\expandafter\ifx\csname SET#2\endcsname\relax
#1% If not set, redefine \next.
\fi
\expandafter
}\next
}
\def\ifsetfail{\doignore{ifset}}
% @ifclear VAR ... @end executes the `...' iff VAR has never been
% defined with @set, or has been undefined with @clear.
%
% The `\else' inside the `\doifset' parameter is a trick to reuse the
% above code: if the variable is not set, do nothing, if it is set,
% then redefine \next to \ifclearfail.
%
\makecond{ifclear}
\def\ifclear{\parsearg{\doifset{\else \let\next=\ifclearfail}}}
\def\ifclearfail{\doignore{ifclear}}
% @ifcommandisdefined CMD ... @end executes the `...' if CMD (written
% without the @) is in fact defined. We can only feasibly check at the
% TeX level, so something like `mathcode' is going to considered
% defined even though it is not a Texinfo command.
%
\makecond{ifcommanddefined}
\def\ifcommanddefined{\parsearg{\doifcmddefined{\let\next=\ifcmddefinedfail}}}
%
\def\doifcmddefined#1#2{{%
\makevalueexpandable
\let\next=\empty
\expandafter\ifx\csname #2\endcsname\relax
#1% If not defined, \let\next as above.
\fi
\expandafter
}\next
}
\def\ifcmddefinedfail{\doignore{ifcommanddefined}}
% @ifcommandnotdefined CMD ... handled similar to @ifclear above.
\makecond{ifcommandnotdefined}
\def\ifcommandnotdefined{%
\parsearg{\doifcmddefined{\else \let\next=\ifcmdnotdefinedfail}}}
\def\ifcmdnotdefinedfail{\doignore{ifcommandnotdefined}}
% Set the `txicommandconditionals' variable, so documents have a way to
% test if the @ifcommand...defined conditionals are available.
\set txicommandconditionals
% @dircategory CATEGORY -- specify a category of the dir file
% which this file should belong to. Ignore this in TeX.
\let\dircategory=\comment
% @defininfoenclose.
\let\definfoenclose=\comment
\message{indexing,}
% Index generation facilities
% Define \newwrite to be identical to plain tex's \newwrite
% except not \outer, so it can be used within macros and \if's.
\edef\newwrite{\makecsname{ptexnewwrite}}
% \newindex {IX} defines an index named IX.
% It automatically defines \IXindex such that
% \IXindex ...rest of line... puts an entry in the index IX.
% It also defines \IXindfile to be the number of the output channel for
% the file that accumulates this index. The file's extension is IX.
%
\def\newindex#1{%
\expandafter\chardef\csname#1indfile\endcsname=0
\expandafter\xdef\csname#1index\endcsname{% % Define @#1index
\noexpand\doindex{#1}}
}
% @defindex foo == \newindex{foo}
%
\def\defindex{\parsearg\newindex}
% Define @defcodeindex, like @defindex except put all entries in @code.
%
\def\defcodeindex{\parsearg\newcodeindex}
%
\def\newcodeindex#1{%
\expandafter\chardef\csname#1indfile\endcsname=0
\expandafter\xdef\csname#1index\endcsname{%
\noexpand\docodeindex{#1}}%
}
% The default indices:
\newindex{cp}% concepts,
\newcodeindex{fn}% functions,
\newcodeindex{vr}% variables,
\newcodeindex{tp}% types,
\newcodeindex{ky}% keys
\newcodeindex{pg}% and programs.
% @synindex foo bar makes index foo feed into index bar.
% Do this instead of @defindex foo if you don't want it as a separate index.
%
% @syncodeindex foo bar similar, but put all entries made for index foo
% inside @code.
%
\def\synindex#1 #2 {\dosynindex\doindex{#1}{#2}}
\def\syncodeindex#1 #2 {\dosynindex\docodeindex{#1}{#2}}
% #1 is \doindex or \docodeindex, #2 the index getting redefined (foo),
% #3 the target index (bar).
\def\dosynindex#1#2#3{%
\requireopenindexfile{#3}%
% redefine \fooindfile:
\expandafter\let\expandafter\temp\expandafter=\csname#3indfile\endcsname
\expandafter\let\csname#2indfile\endcsname=\temp
% redefine \fooindex:
\expandafter\xdef\csname#2index\endcsname{\noexpand#1{#3}}%
}
% Define \doindex, the driver for all index macros.
% Argument #1 is generated by the calling \fooindex macro,
% and it is the two-letter name of the index.
\def\doindex#1{\edef\indexname{#1}\parsearg\doindexxxx}
\def\doindexxxx #1{\doind{\indexname}{#1}}
% like the previous two, but they put @code around the argument.
\def\docodeindex#1{\edef\indexname{#1}\parsearg\docodeindexxxx}
\def\docodeindexxxx #1{\docind{\indexname}{#1}}
% \definedummyword defines \#1 as \string\#1\space, thus effectively
% preventing its expansion. This is used only for control words,
% not control letters, because the \space would be incorrect for
% control characters, but is needed to separate the control word
% from whatever follows.
%
% These can be used both for control words that take an argument and
% those that do not. If it is followed by {arg} in the input, then
% that will dutifully get written to the index (or wherever).
%
% For control letters, we have \definedummyletter, which omits the
% space.
%
\def\definedummyword #1{\def#1{\string#1\space}}%
\def\definedummyletter#1{\def#1{\string#1}}%
% Used for the aux, toc and index files to prevent expansion of Texinfo
% commands. Most of the commands are controlled through the
% \ifdummies conditional.
%
\def\atdummies{%
\dummiestrue
%
\definedummyletter\@%
\definedummyletter\ %
\definedummyletter\{%
\definedummyletter\}%
\definedummyletter\&%
%
\definedummyletter\_%
\definedummyletter\-%
%
\definedummyword\subentry
%
% We want to disable all macros so that they are not expanded by \write.
\let\commondummyword\definedummyword
\macrolist
\let\value\dummyvalue
%
\turnoffactive
}
\newif\ifdummies
\newif\ifindexnofonts
\def\commondummyletter#1{%
\expandafter\let\csname\string#1:impl\endcsname#1%
\edef#1{%
\noexpand\ifindexnofonts
% empty expansion
\noexpand\else
\noexpand\ifdummies\string#1%
\noexpand\else
\noexpand\jumptwofi % dispose of the \fi
\expandafter\noexpand\csname\string#1:impl\endcsname
\noexpand\fi
\noexpand\fi}%
}
\def\commondummyaccent#1{%
\expandafter\let\csname\string#1:impl\endcsname#1%
\edef#1{%
\noexpand\ifindexnofonts
\noexpand\expandafter % dispose of \else ... \fi
\noexpand\asis
\noexpand\else
\noexpand\ifdummies\string#1%
\noexpand\else
\noexpand\jumptwofi % dispose of the \fi
\expandafter\noexpand\csname\string#1:impl\endcsname
\noexpand\fi
\noexpand\fi}%
}
% Like \commondummyaccent but add a \space at the end of the dummy expansion
% #2 is the expansion used for \indexnofonts. #2 is always followed by
% \asis to remove a pair of following braces.
\def\commondummyword#1#2{%
\expandafter\let\csname\string#1:impl\endcsname#1%
\expandafter\def\csname\string#1:ixnf\endcsname{#2\asis}%
\edef#1{%
\noexpand\ifindexnofonts
\noexpand\expandafter % dispose of \else ... \fi
\expandafter\noexpand\csname\string#1:ixnf\endcsname
\noexpand\else
\noexpand\ifdummies\string#1\space
\noexpand\else
\noexpand\jumptwofi % dispose of the \fi \fi
\expandafter\noexpand\csname\string#1:impl\endcsname
\noexpand\fi
\noexpand\fi}%
}
\def\jumptwofi#1\fi\fi{\fi\fi#1}
% For \atdummies and \indexnofonts. \atdummies sets
% \dummiestrue and \indexnofonts sets \indexnofontstrue.
\def\definedummies{
% @-sign is always an escape character when reading auxiliary files
\escapechar = `\@
%
\commondummyletter\!%
\commondummyaccent\"%
\commondummyaccent\'%
\commondummyletter\*%
\commondummyaccent\,%
\commondummyletter\.%
\commondummyletter\/%
\commondummyletter\:%
\commondummyaccent\=%
\commondummyletter\?%
\commondummyaccent\^%
\commondummyaccent\`%
\commondummyaccent\~%
%
% Control letters and accents.
\commondummyword\u {}%
\commondummyword\v {}%
\commondummyword\H {}%
\commondummyword\dotaccent {}%
\commondummyword\ogonek {}%
\commondummyword\ringaccent {}%
\commondummyword\tieaccent {}%
\commondummyword\ubaraccent {}%
\commondummyword\udotaccent {}%
\commondummyword\dotless {}%
%
% Texinfo font commands.
\commondummyword\b {}%
\commondummyword\i {}%
\commondummyword\r {}%
\commondummyword\sansserif {}%
\commondummyword\sc {}%
\commondummyword\slanted {}%
\commondummyword\t {}%
%
% Commands that take arguments.
\commondummyword\abbr {}%
\commondummyword\acronym {}%
\commondummyword\anchor {}%
\commondummyword\cite {}%
\commondummyword\code {}%
\commondummyword\command {}%
\commondummyword\dfn {}%
\commondummyword\dmn {}%
\commondummyword\email {}%
\commondummyword\emph {}%
\commondummyword\env {}%
\commondummyword\file {}%
\commondummyword\image {}%
\commondummyword\indicateurl{}%
\commondummyword\inforef {}%
\commondummyword\kbd {}%
\commondummyword\key {}%
\commondummyword\link {}%
\commondummyword\math {}%
\commondummyword\option {}%
\commondummyword\pxref {}%
\commondummyword\ref {}%
\commondummyword\samp {}%
\commondummyword\strong {}%
\commondummyword\tie {}%
\commondummyword\U {}%
\commondummyword\uref {}%
\commondummyword\url {}%
\commondummyword\var {}%
\commondummyword\verb {}%
\commondummyword\w {}%
\commondummyword\xref {}%
%
\commondummyword\AA {AA}%
\commondummyword\AE {AE}%
\commondummyword\DH {DZZ}%
\commondummyword\L {L}%
\commondummyword\O {O}%
\commondummyword\OE {OE}%
\commondummyword\TH {TH}%
\commondummyword\aa {aa}%
\commondummyword\ae {ae}%
\commondummyword\dh {dzz}%
\commondummyword\exclamdown {!}%
\commondummyword\l {l}%
\commondummyword\o {o}%
\commondummyword\oe {oe}%
\commondummyword\ordf {a}%
\commondummyword\ordm {o}%
\commondummyword\questiondown {?}%
\commondummyword\ss {ss}%
\commondummyword\th {th}%
%
\commondummyword\LaTeX {LaTeX}%
\commondummyword\TeX {TeX}%
%
% Assorted special characters.
\commondummyword\ampchar {\normalamp}%
\commondummyword\atchar {\@}%
\commondummyword\arrow {->}%
\commondummyword\backslashchar {\realbackslash}%
\commondummyword\bullet {bullet}%
\commondummyword\comma {,}%
\commondummyword\copyright {copyright}%
\commondummyword\dots {...}%
\commondummyword\enddots {...}%
\commondummyword\entrybreak {}%
\commondummyword\equiv {===}%
\commondummyword\error {error}%
\commondummyword\euro {euro}%
\commondummyword\expansion {==>}%
\commondummyword\geq {>=}%
\commondummyword\guillemetleft {<<}%
\commondummyword\guillemetright {>>}%
\commondummyword\guilsinglleft {<}%
\commondummyword\guilsinglright {>}%
\commondummyword\lbracechar {\{}%
\commondummyword\leq {<=}%
\commondummyword\mathopsup {sup}%
\commondummyword\minus {-}%
\commondummyword\pounds {pounds}%
\commondummyword\point {.}%
\commondummyword\print {-|}%
\commondummyword\quotedblbase {"}%
\commondummyword\quotedblleft {"}%
\commondummyword\quotedblright {"}%
\commondummyword\quoteleft {`}%
\commondummyword\quoteright {'}%
\commondummyword\quotesinglbase {,}%
\commondummyword\rbracechar {\}}%
\commondummyword\registeredsymbol {R}%
\commondummyword\result {=>}%
\commondummyword\sub {}%
\commondummyword\sup {}%
\commondummyword\textdegree {o}%
}
\let\indexlbrace\relax
\let\indexrbrace\relax
\let\indexatchar\relax
\let\indexbackslash\relax
{\catcode`\@=0
\catcode`\\=13
@gdef@backslashdisappear{@def\{}}
}
{
\catcode`\<=13
\catcode`\-=13
\catcode`\`=13
\gdef\indexnonalnumdisappear{%
\ifflagclear{txiindexlquoteignore}{}{%
% @set txiindexlquoteignore makes us ignore left quotes in the sort term.
% (Introduced for FSFS 2nd ed.)
\let`=\empty
}%
%
\ifflagclear{txiindexbackslashignore}{}{%
\backslashdisappear
}%
\ifflagclear{txiindexhyphenignore}{}{%
\def-{}%
}%
\ifflagclear{txiindexlessthanignore}{}{%
\def<{}%
}%
\ifflagclear{txiindexatsignignore}{}{%
\def\@{}%
}%
}
\gdef\indexnonalnumreappear{%
\let-\normaldash
\let<\normalless
}
}
% \indexnofonts is used when outputting the strings to sort the index
% by, and when constructing control sequence names. It eliminates all
% control sequences and just writes whatever the best ASCII sort string
% would be for a given command (usually its argument).
%
\def\indexnofonts{%
\indexnofontstrue
%
\def\ { }%
\def\@{@}%
\def\_{\normalunderscore}%
\def\-{}% @- shouldn't affect sorting
%
\uccode`\1=`\{ \uppercase{\def\{{1}}%
\uccode`\1=`\} \uppercase{\def\}{1}}%
\let\lbracechar\{%
\let\rbracechar\}%
%
%
% We need to get rid of all macros, leaving only the arguments (if present).
% Of course this is not nearly correct, but it is the best we can do for now.
%
% Since macro invocations are followed by braces, we can just redefine them
% to take a single TeX argument. The case of a macro invocation that
% goes to end-of-line is not handled.
%
\def\commondummyword##1{\let##1\asis}%
\macrolist
\let\value\indexnofontsvalue
}
% #1 is the index name, #2 is the entry text.
\def\doind#1#2{%
\iflinks
{%
%
\requireopenindexfile{#1}%
\edef\writeto{\csname#1indfile\endcsname}%
%
\def\indextext{#2}%
\safewhatsit\doindwrite
}%
\fi
}
% Same as \doind, but for code indices
\def\docind#1#2{%
\iflinks
{%
%
\requireopenindexfile{#1}%
\edef\writeto{\csname#1indfile\endcsname}%
%
\def\indextext{#2}%
\safewhatsit\docindwrite
}%
\fi
}
% Check if an index file has been opened, and if not, open it.
\def\requireopenindexfile#1{%
\ifnum\csname #1indfile\endcsname=0
\expandafter\newwrite \csname#1indfile\endcsname
\edef\suffix{#1}%
% A .fls suffix would conflict with the file extension for the output
% of -recorder, so use .f1s instead.
\ifx\suffix\indexisfl\def\suffix{f1}\fi
% Open the file
\immediate\openout\csname#1indfile\endcsname \jobname.\suffix
% Using \immediate above here prevents an object entering into the current
% box, which could confound checks such as those in \safewhatsit for
% preceding skips.
\typeout{Writing index file \jobname.\suffix}%
\fi}
\def\indexisfl{fl}
% Definition for writing index entry sort key.
{
\catcode`\-=13
\gdef\indexwritesortas{%
\begingroup
\indexnonalnumreappear
\indexwritesortasxxx}
\gdef\indexwritesortasxxx#1{%
\xdef\indexsortkey{#1}\endgroup}
}
\def\indexwriteseealso#1{
\gdef\pagenumbertext{\string\seealso{#1}}%
}
\def\indexwriteseeentry#1{
\gdef\pagenumbertext{\string\seeentry{#1}}%
}
% The default definitions
\def\sortas#1{}%
\def\seealso#1{\i{\putwordSeeAlso}\ #1}% for sorted index file only
\def\putwordSeeAlso{See also}
\def\seeentry#1{\i{\putwordSee}\ #1}% for sorted index file only
% Given index entry text like "aaa @subentry bbb @sortas{ZZZ}":
% * Set \bracedtext to "{aaa}{bbb}"
% * Set \fullindexsortkey to "aaa @subentry ZZZ"
% * If @seealso occurs, set \pagenumbertext
%
\def\splitindexentry#1{%
\gdef\fullindexsortkey{}%
\xdef\bracedtext{}%
\def\sep{}%
\def\seealso##1{}%
\def\seeentry##1{}%
\expandafter\doindexsegment#1\subentry\finish\subentry
}
% append the results from the next segment
\def\doindexsegment#1\subentry{%
\def\segment{#1}%
\ifx\segment\isfinish
\else
%
% Fully expand the segment, throwing away any @sortas directives, and
% trim spaces.
\edef\trimmed{\segment}%
\edef\trimmed{\expandafter\eatspaces\expandafter{\trimmed}}%
\ifincodeindex
\edef\trimmed{\noexpand\code{\trimmed}}%
\fi
%
\xdef\bracedtext{\bracedtext{\trimmed}}%
%
% Get the string to sort by. Process the segment with all
% font commands turned off.
\bgroup
\let\sortas\indexwritesortas
\let\seealso\indexwriteseealso
\let\seeentry\indexwriteseeentry
\indexnofonts
% The braces around the commands are recognized by texindex.
\def\lbracechar{{\string\indexlbrace}}%
\def\rbracechar{{\string\indexrbrace}}%
\let\{=\lbracechar
\let\}=\rbracechar
\def\@{{\string\indexatchar}}%
\def\atchar##1{\@}%
\def\backslashchar{{\string\indexbackslash}}%
\uccode`\~=`\\ \uppercase{\let~\backslashchar}%
%
\let\indexsortkey\empty
\global\let\pagenumbertext\empty
% Execute the segment and throw away the typeset output. This executes
% any @sortas or @seealso commands in this segment.
\setbox\dummybox = \hbox{\segment}%
\ifx\indexsortkey\empty{%
\indexnonalnumdisappear
\xdef\trimmed{\segment}%
\xdef\trimmed{\expandafter\eatspaces\expandafter{\trimmed}}%
\xdef\indexsortkey{\trimmed}%
\ifx\indexsortkey\empty
\message{Empty index sort key near line \the\inputlineno}%
\xdef\indexsortkey{ }%
\fi
}\fi
%
% Append to \fullindexsortkey.
\edef\tmp{\gdef\noexpand\fullindexsortkey{%
\fullindexsortkey\sep\indexsortkey}}%
\tmp
\egroup
\def\sep{\subentry}%
%
\expandafter\doindexsegment
\fi
}
\def\isfinish{\finish}%
\newbox\dummybox % used above
\let\subentry\relax
% Use \ instead of @ in index files. To support old texi2dvi and texindex.
% This works without changing the escape character used in the toc or aux
% files because the index entries are fully expanded here, and \string uses
% the current value of \escapechar.
\def\escapeisbackslash{\escapechar=`\\}
% Uncomment to use \ in index files by default. Old texi2dvi (before 2019)
% didn't support @ as the escape character (as it checked for "\entry" in
% the files, and not "@entry").
% In the future we can remove this flag and simplify the code for
% index files and backslashes, once the support is no longer likely to be
% useful.
%
% \set txiindexescapeisbackslash
% Write the entry in \indextext to the index file.
%
\newif\ifincodeindex
\def\doindwrite{\incodeindexfalse\doindwritex}
\def\docindwrite{\incodeindextrue\doindwritex}
\def\doindwritex{%
\maybemarginindex
%
\atdummies
%
\ifflagclear{txiindexescapeisbackslash}{}{\escapeisbackslash}%
%
% For texindex which always views { and } as separators.
\def\{{\lbracechar{}}%
\def\}{\rbracechar{}}%
\uccode`\~=`\\ \uppercase{\def~{\backslashchar{}}}%
%
% Split the entry into primary entry and any subentries, and get the index
% sort key.
\splitindexentry\indextext
%
% Set up the complete index entry, with both the sort key and
% the original text, including any font commands. We write
% three arguments to \entry to the .?? file (four in the
% subentry case), texindex reduces to two when writing the .??s
% sorted result.
%
\edef\temp{%
\write\writeto{%
\string\entry{\fullindexsortkey}%
{\ifx\pagenumbertext\empty\noexpand\folio\else\pagenumbertext\fi}%
\bracedtext}%
}%
\temp
}
% Put the index entry in the margin if desired (undocumented).
\def\maybemarginindex{%
\ifx\SETmarginindex\relax\else
\insert\margin{\hbox{\vrule height8pt depth3pt width0pt \relax\indextext}}%
\fi
}
\let\SETmarginindex=\relax
% Take care of unwanted page breaks/skips around a whatsit:
%
% If a skip is the last thing on the list now, preserve it
% by backing up by \lastskip, doing the \write, then inserting
% the skip again. Otherwise, the whatsit generated by the
% \write or \pdfdest will make \lastskip zero. The result is that
% sequences like this:
% @end defun
% @tindex whatever
% @defun ...
% will have extra space inserted, because the \medbreak in the
% start of the @defun won't see the skip inserted by the @end of
% the previous defun.
%
% But don't do any of this if we're not in vertical mode. We
% don't want to do a \vskip and prematurely end a paragraph.
%
% Avoid page breaks due to these extra skips, too.
%
% But wait, there is a catch there:
% We'll have to check whether \lastskip is zero skip. \ifdim is not
% sufficient for this purpose, as it ignores stretch and shrink parts
% of the skip. The only way seems to be to check the textual
% representation of the skip.
%
% The following is almost like \def\zeroskipmacro{0.0pt} except that
% the ``p'' and ``t'' characters have catcode \other, not 11 (letter).
%
\edef\zeroskipmacro{\expandafter\the\csname z@skip\endcsname}
%
\newskip\whatsitskip
\newcount\whatsitpenalty
%
% ..., ready, GO:
%
\def\safewhatsit#1{\ifhmode
#1%
\else
% \lastskip and \lastpenalty cannot both be nonzero simultaneously.
\whatsitskip = \lastskip
\edef\lastskipmacro{\the\lastskip}%
\whatsitpenalty = \lastpenalty
%
% If \lastskip is nonzero, that means the last item was a
% skip. And since a skip is discardable, that means this
% -\whatsitskip glue we're inserting is preceded by a
% non-discardable item, therefore it is not a potential
% breakpoint, therefore no \nobreak needed.
\ifx\lastskipmacro\zeroskipmacro
\else
\vskip-\whatsitskip
\fi
%
#1%
%
\ifx\lastskipmacro\zeroskipmacro
% If \lastskip was zero, perhaps the last item was a penalty, and
% perhaps it was >=10000, e.g., a \nobreak. In that case, we want
% to re-insert the same penalty (values >10000 are used for various
% signals); since we just inserted a non-discardable item, any
% following glue (such as a \parskip) would be a breakpoint. For example:
% @deffn deffn-whatever
% @vindex index-whatever
% Description.
% would allow a break between the index-whatever whatsit
% and the "Description." paragraph.
\ifnum\whatsitpenalty>9999 \penalty\whatsitpenalty \fi
\else
% On the other hand, if we had a nonzero \lastskip,
% this make-up glue would be preceded by a non-discardable item
% (the whatsit from the \write), so we must insert a \nobreak.
\nobreak\vskip\whatsitskip
\fi
\fi}
% The index entry written in the file actually looks like
% \entry {sortstring}{page}{topic}
% or
% \entry {sortstring}{page}{topic}{subtopic}
% The texindex program reads in these files and writes files
% containing these kinds of lines:
% \initial {c}
% before the first topic whose initial is c
% \entry {topic}{pagelist}
% for a topic that is used without subtopics
% \primary {topic}
% \entry {topic}{}
% for the beginning of a topic that is used with subtopics
% \secondary {subtopic}{pagelist}
% for each subtopic.
% \secondary {subtopic}{}
% for a subtopic with sub-subtopics
% \tertiary {subtopic}{subsubtopic}{pagelist}
% for each sub-subtopic.
% Define the user-accessible indexing commands
% @findex, @vindex, @kindex, @cindex.
\def\findex {\fnindex}
\def\kindex {\kyindex}
\def\cindex {\cpindex}
\def\vindex {\vrindex}
\def\tindex {\tpindex}
\def\pindex {\pgindex}
% Define the macros used in formatting output of the sorted index material.
% @printindex causes a particular index (the ??s file) to get printed.
% It does not print any chapter heading (usually an @unnumbered).
%
\parseargdef\printindex{\begingroup
\dobreak \chapheadingskip{10000}%
%
\smallfonts \rm
\tolerance = 9500
\plainfrenchspacing
\everypar = {}% don't want the \kern\-parindent from indentation suppression.
%
% See comment in \requireopenindexfile.
\def\indexname{#1}\ifx\indexname\indexisfl\def\indexname{f1}\fi
%
% See if the index file exists and is nonempty.
\openin 1 \jobname.\indexname s
\ifeof 1
% \enddoublecolumns gets confused if there is no text in the index,
% and it loses the chapter title and the aux file entries for the
% index. The easiest way to prevent this problem is to make sure
% there is some text.
\putwordIndexNonexistent
\typeout{No file \jobname.\indexname s.}%
\else
% If the index file exists but is empty, then \openin leaves \ifeof
% false. We have to make TeX try to read something from the file, so
% it can discover if there is anything in it.
\read 1 to \thisline
\ifeof 1
\putwordIndexIsEmpty
\else
\expandafter\printindexzz\thisline\relax\relax\finish%
\fi
\fi
\closein 1
\endgroup}
% If the index file starts with a backslash, forgo reading the index
% file altogether. If somebody upgrades texinfo.tex they may still have
% old index files using \ as the escape character. Reading this would
% at best lead to typesetting garbage, at worst a TeX syntax error.
\def\printindexzz#1#2\finish{%
\ifflagclear{txiindexescapeisbackslash}{%
\uccode`\~=`\\ \uppercase{\if\noexpand~}\noexpand#1
\ifflagclear{txiskipindexfileswithbackslash}{%
\errmessage{%
ERROR: A sorted index file in an obsolete format was skipped.
To fix this problem, please upgrade your version of 'texi2dvi'
or 'texi2pdf' to that at .
If you are using an old version of 'texindex' (part of the Texinfo
distribution), you may also need to upgrade to a newer version (at least 6.0).
You may be able to typeset the index if you run
'texindex \jobname.\indexname' yourself.
You could also try setting the 'txiindexescapeisbackslash' flag by
running a command like
'texi2dvi -t "@set txiindexescapeisbackslash" \jobname.texi'. If you do
this, Texinfo will try to use index files in the old format.
If you continue to have problems, deleting the index files and starting again
might help (with 'rm \jobname.?? \jobname.??s')%
}%
}{%
(Skipped sorted index file in obsolete format)
}%
\else
\begindoublecolumns
\input \jobname.\indexname s
\enddoublecolumns
\fi
}{%
\begindoublecolumns
\catcode`\\=0\relax
%
% Make @ an escape character to give macros a chance to work. This
% should work because we (hopefully) don't otherwise use @ in index files.
%\catcode`\@=12\relax
\catcode`\@=0\relax
\input \jobname.\indexname s
\enddoublecolumns
}%
}
% These macros are used by the sorted index file itself.
% Change them to control the appearance of the index.
{\catcode`\/=13 \catcode`\-=13 \catcode`\^=13 \catcode`\~=13 \catcode`\_=13
\catcode`\|=13 \catcode`\<=13 \catcode`\>=13 \catcode`\+=13 \catcode`\"=13
\catcode`\$=3
\gdef\initialglyphs{%
% special control sequences used in the index sort key
\let\indexlbrace\{%
\let\indexrbrace\}%
\let\indexatchar\@%
\def\indexbackslash{\math{\backslash}}%
%
% Some changes for non-alphabetic characters. Using the glyphs from the
% math fonts looks more consistent than the typewriter font used elsewhere
% for these characters.
\uccode`\~=`\\ \uppercase{\def~{\math{\backslash}}}
%
% In case @\ is used for backslash
\uppercase{\let\\=~}
% Can't get bold backslash so don't use bold forward slash
\catcode`\/=13
\def/{{\secrmnotbold \normalslash}}%
\def-{{\normaldash\normaldash}}% en dash `--'
\def^{{\chapbf \normalcaret}}%
\def~{{\chapbf \normaltilde}}%
\def\_{%
\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em }%
\def|{$\vert$}%
\def<{$\less$}%
\def>{$\gtr$}%
\def+{$\normalplus$}%
}}
\def\initial{%
\bgroup
\initialglyphs
\initialx
}
\def\initialx#1{%
% Remove any glue we may have, we'll be inserting our own.
\removelastskip
%
% We like breaks before the index initials, so insert a bonus.
% The glue before the bonus allows a little bit of space at the
% bottom of a column to reduce an increase in inter-line spacing.
\nobreak
\vskip 0pt plus 5\baselineskip
\penalty -300
\vskip 0pt plus -5\baselineskip
%
% Typeset the initial. Making this add up to a whole number of
% baselineskips increases the chance of the dots lining up from column
% to column. It still won't often be perfect, because of the stretch
% we need before each entry, but it's better.
%
% No shrink because it confuses \balancecolumns.
\vskip 1.67\baselineskip plus 1\baselineskip
\leftline{\secfonts \kern-0.05em \secbf #1}%
% \secfonts is inside the argument of \leftline so that the change of
% \baselineskip will not affect any glue inserted before the vbox that
% \leftline creates.
% Do our best not to break after the initial.
\nobreak
\vskip .33\baselineskip plus .1\baselineskip
\egroup % \initialglyphs
}
\newdimen\entryrightmargin
\entryrightmargin=0pt
% amount to indent subsequent lines in an entry when it spans more than
% one line.
\newdimen\entrycontskip
\entrycontskip=1em
% for PDF output, whether to make the text of the entry a link to the page
% number. set for @contents and @shortcontents where there is only one
% page number.
\newif\iflinkentrytext
% \entry typesets a paragraph consisting of the text (#1), dot leaders, and
% then page number (#2) flushed to the right margin. It is used for index
% and table of contents entries. The paragraph is indented by \leftskip.
%
\def\entry{%
\begingroup
%
% Start a new paragraph if necessary, so our assignments below can't
% affect previous text.
\par
%
% No extra space above this paragraph.
\parskip = 0in
%
% When reading the text of entry, convert explicit line breaks
% from @* into spaces. The user might give these in long section
% titles, for instance.
\def\*{\unskip\space\ignorespaces}%
\def\entrybreak{\hfil\break}% An undocumented command
%
% Swallow the left brace of the text (first parameter):
\afterassignment\doentry
\let\temp =
}
\def\entrybreak{\unskip\space\ignorespaces}%
\def\doentry{%
% Save the text of the entry in \boxA
\global\setbox\boxA=\hbox\bgroup
\bgroup % Instead of the swallowed brace.
\noindent
\aftergroup\finishentry
% And now comes the text of the entry.
% Not absorbing as a macro argument reduces the chance of problems
% with catcodes occurring.
}
{\catcode`\@=11
% #1 is the page number
\gdef\finishentry#1{%
\egroup % end \boxA
\dimen@ = \wd\boxA % Length of text of entry
% add any leaders and page number to \boxA.
\global\setbox\boxA=\hbox\bgroup
\ifpdforxetex
\iflinkentrytext
\pdflinkpage{#1}{\unhbox\boxA}%
\else
\unhbox\boxA
\fi
\else
\unhbox\boxA
\fi
%
% Get the width of the page numbers, and only use
% leaders if they are present.
\global\setbox\boxB = \hbox{#1}%
\ifdim\wd\boxB = 0pt
\null\nobreak\hfill\ %
\else
%
\null\nobreak\indexdotfill % Have leaders before the page number.
%
\ifpdforxetex
\pdfgettoks#1.%
\hskip\skip\thinshrinkable\the\toksA
\else
\hskip\skip\thinshrinkable #1%
\fi
\fi
\egroup % end \boxA
%
% now output
\ifdim\wd\boxB = 0pt
\noindent\unhbox\boxA\par
\nobreak
\else\bgroup
% We want the text of the entries to be aligned to the left, and the
% page numbers to be aligned to the right.
%
\parindent = 0pt
\advance\leftskip by 0pt plus 1fil
\advance\leftskip by 0pt plus -1fill
\rightskip = 0pt plus -1fil
\advance\rightskip by 0pt plus 1fill
% Cause last line, which could consist of page numbers on their own
% if the list of page numbers is long, to be aligned to the right.
\parfillskip=0pt plus -1fill
%
\advance\rightskip by \entryrightmargin
%
\dimen@ii = \hsize
\advance\dimen@ii by -1\leftskip
\advance\dimen@ii by -1\entryrightmargin
\ifdim\wd\boxA > \dimen@ii % If the entry doesn't fit in one line
\ifdim\dimen@ > 0.8\dimen@ii % due to long index text
\advance\leftskip by 0pt plus 1fill % ragged right
%
% Indent all lines but the first one.
\advance\leftskip by \entrycontskip
\advance\parindent by -\entrycontskip
\fi\fi
\indent % start paragraph
\unhbox\boxA
%
% Do not prefer a separate line ending with a hyphen to fewer lines.
\finalhyphendemerits = 0
%
% Word spacing - no stretch
\spaceskip=\fontdimen2\font minus \fontdimen4\font
%
\linepenalty=1000 % Discourage line breaks.
\hyphenpenalty=5000 % Discourage hyphenation.
%
\par % format the paragraph
\egroup % The \vbox
\fi
\endgroup
}}
\newskip\thinshrinkable
\skip\thinshrinkable=.15em minus .15em
% Like plain.tex's \dotfill, except uses up at least 0.5 em.
% The filll stretch here overpowers both the fil and fill stretch to push
% the page number to the right.
\def\indexdotfill{\cleaders
\hbox{$\mathsurround=0pt \mkern1.5mu.\mkern1.5mu$}\hskip 0.5em plus 1filll}
\def\primary #1{\line{#1\hfil}}
\def\secondary{\indententry{0.5cm}}
\def\tertiary{\indententry{1cm}}
\def\indententry#1#2#3{%
\bgroup
\leftskip=#1
\entry{#2}{#3}%
\egroup
}
% Define two-column mode, which we use to typeset indexes.
% Adapted from the TeXbook, page 416, which is to say,
% the manmac.tex format used to print the TeXbook itself.
\catcode`\@=11 % private names
\newbox\partialpage
\newdimen\doublecolumnhsize
\def\begindoublecolumns{\begingroup % ended by \enddoublecolumns
% If not much space left on page, start a new page.
\ifdim\pagetotal>0.8\vsize\vfill\eject\fi
%
% Grab any single-column material above us.
\output = {%
\savetopmark
%
\global\setbox\partialpage = \vbox{%
% Unvbox the main output page.
\unvbox\PAGE
\kern-\topskip \kern\baselineskip
}%
}%
\eject % run that output routine to set \partialpage
%
% Use the double-column output routine for subsequent pages.
\output = {\doublecolumnout}%
%
% Change the page size parameters. We could do this once outside this
% routine, in each of @smallbook, @afourpaper, and the default 8.5x11
% format, but then we repeat the same computation. Repeating a couple
% of assignments once per index is clearly meaningless for the
% execution time, so we may as well do it in one place.
%
% First we halve the line length, less a little for the gutter between
% the columns. We compute the gutter based on the line length, so it
% changes automatically with the paper format. The magic constant
% below is chosen so that the gutter has the same value (well, +-<1pt)
% as it did when we hard-coded it.
%
% We put the result in a separate register, \doublecolumnhsize, so we
% can restore it in \pagesofar, after \hsize itself has (potentially)
% been clobbered.
%
\doublecolumnhsize = \hsize
\advance\doublecolumnhsize by -.04154\hsize
\divide\doublecolumnhsize by 2
\hsize = \doublecolumnhsize
%
% Get the available space for the double columns -- the normal
% (undoubled) page height minus any material left over from the
% previous page.
\advance\vsize by -\ht\partialpage
\vsize = 2\vsize
%
% For the benefit of balancing columns
\advance\baselineskip by 0pt plus 0.5pt
}
% The double-column output routine for all double-column pages except
% the last, which is done by \balancecolumns.
%
\def\doublecolumnout{%
%
\savetopmark
\splittopskip=\topskip \splitmaxdepth=\maxdepth
\dimen@ = \vsize
\divide\dimen@ by 2
%
% box0 will be the left-hand column, box2 the right.
\setbox0=\vsplit\PAGE to\dimen@ \setbox2=\vsplit\PAGE to\dimen@
\global\advance\vsize by 2\ht\partialpage
\onepageout\pagesofar % empty except for the first time we are called
\unvbox\PAGE
\penalty\outputpenalty
}
%
% Re-output the contents of the output page -- any previous material,
% followed by the two boxes we just split, in box0 and box2.
\def\pagesofar{%
\unvbox\partialpage
%
\hsize = \doublecolumnhsize
\wd0=\hsize \wd2=\hsize
\hbox to\txipagewidth{\box0\hfil\box2}%
}
% Finished with double columns.
\def\enddoublecolumns{%
% The following penalty ensures that the page builder is exercised
% _before_ we change the output routine. This is necessary in the
% following situation:
%
% The last section of the index consists only of a single entry.
% Before this section, \pagetotal is less than \pagegoal, so no
% break occurs before the last section starts. However, the last
% section, consisting of \initial and the single \entry, does not
% fit on the page and has to be broken off. Without the following
% penalty the page builder will not be exercised until \eject
% below, and by that time we'll already have changed the output
% routine to the \balancecolumns version, so the next-to-last
% double-column page will be processed with \balancecolumns, which
% is wrong: The two columns will go to the main vertical list, with
% the broken-off section in the recent contributions. As soon as
% the output routine finishes, TeX starts reconsidering the page
% break. The two columns and the broken-off section both fit on the
% page, because the two columns now take up only half of the page
% goal. When TeX sees \eject from below which follows the final
% section, it invokes the new output routine that we've set after
% \balancecolumns below; \onepageout will try to fit the two columns
% and the final section into the vbox of \txipageheight (see
% \pagebody), causing an overfull box.
%
% Note that glue won't work here, because glue does not exercise the
% page builder, unlike penalties (see The TeXbook, pp. 280-281).
\penalty0
%
\output = {%
% Split the last of the double-column material.
\savetopmark
\balancecolumns
}%
\eject % call the \output just set
\ifdim\pagetotal=0pt
% Having called \balancecolumns once, we do not
% want to call it again. Therefore, reset \output to its normal
% definition right away.
\global\output=\expandafter{\the\defaultoutput}
%
\endgroup % started in \begindoublecolumns
% Leave the double-column material on the current page, no automatic
% page break.
\box\balancedcolumns
%
% \pagegoal was set to the doubled \vsize above, since we restarted
% the current page. We're now back to normal single-column
% typesetting, so reset \pagegoal to the normal \vsize.
\global\vsize = \txipageheight %
\pagegoal = \txipageheight %
\else
% We had some left-over material. This might happen when \doublecolumnout
% is called in \balancecolumns. Try again.
\expandafter\enddoublecolumns
\fi
}
\newbox\balancedcolumns
\setbox\balancedcolumns=\vbox{shouldnt see this}%
%
% Only called for the last of the double column material. \doublecolumnout
% does the others.
\def\balancecolumns{%
\setbox0 = \vbox{\unvbox\PAGE}% like \box255 but more efficient, see p.120.
\dimen@ = \ht0
\ifdim\dimen@<7\baselineskip
% Don't split a short final column in two.
\setbox2=\vbox{}%
\global\setbox\balancedcolumns=\vbox{\pagesofar}%
\else
% double the leading vertical space
\advance\dimen@ by \topskip
\advance\dimen@ by-\baselineskip
\divide\dimen@ by 2 % target to split to
\dimen@ii = \dimen@
\splittopskip = \topskip
% Loop until left column is at least as high as the right column.
{%
\vbadness = 10000
\loop
\global\setbox3 = \copy0
\global\setbox1 = \vsplit3 to \dimen@
\ifdim\ht1<\ht3
\global\advance\dimen@ by 1pt
\repeat
}%
% Now the left column is in box 1, and the right column in box 3.
%
% Check whether the left column has come out higher than the page itself.
% (Note that we have doubled \vsize for the double columns, so
% the actual height of the page is 0.5\vsize).
\ifdim2\ht1>\vsize
% It appears that we have been called upon to balance too much material.
% Output some of it with \doublecolumnout, leaving the rest on the page.
\setbox\PAGE=\box0
\doublecolumnout
\else
% Compare the heights of the two columns.
\ifdim4\ht1>5\ht3
% Column heights are too different, so don't make their bottoms
% flush with each other.
\setbox2=\vbox to \ht1 {\unvbox3\vfill}%
\setbox0=\vbox to \ht1 {\unvbox1\vfill}%
\else
% Make column bottoms flush with each other.
\setbox2=\vbox to\ht1{\unvbox3\unskip}%
\setbox0=\vbox to\ht1{\unvbox1\unskip}%
\fi
\global\setbox\balancedcolumns=\vbox{\pagesofar}%
\fi
\fi
%
}
\catcode`\@ = \other
\message{sectioning,}
% Chapters, sections, etc.
% Let's start with @part.
\parseargdef\part{\partzzz{#1}}
\def\partzzz#1{%
\chapoddpage
\null
\vskip.3\vsize % move it down on the page a bit
\begingroup
\noindent \titlefonts\rm #1\par % the text
\let\lastnode=\empty % no node to associate with
\writetocentry{part}{#1}{}% but put it in the toc
\headingsoff % no headline or footline on the part page
% This outputs a mark at the end of the page that clears \thischapter
% and \thissection, as is done in \startcontents.
\let\pchapsepmacro\relax
\chapmacro{}{Yomitfromtoc}{}%
\chapoddpage
\endgroup
}
% \unnumberedno is an oxymoron. But we count the unnumbered
% sections so that we can refer to them unambiguously in the pdf
% outlines by their "section number". We avoid collisions with chapter
% numbers by starting them at 10000. (If a document ever has 10000
% chapters, we're in trouble anyway, I'm sure.)
\newcount\unnumberedno \unnumberedno = 10000
\newcount\chapno
\newcount\secno \secno=0
\newcount\subsecno \subsecno=0
\newcount\subsubsecno \subsubsecno=0
% This counter is funny since it counts through charcodes of letters A, B, ...
\newcount\appendixno \appendixno = `\@
%
% \def\appendixletter{\char\the\appendixno}
% We do the following ugly conditional instead of the above simple
% construct for the sake of pdftex, which needs the actual
% letter in the expansion, not just typeset.
%
\def\appendixletter{%
\ifnum\appendixno=`A A%
\else\ifnum\appendixno=`B B%
\else\ifnum\appendixno=`C C%
\else\ifnum\appendixno=`D D%
\else\ifnum\appendixno=`E E%
\else\ifnum\appendixno=`F F%
\else\ifnum\appendixno=`G G%
\else\ifnum\appendixno=`H H%
\else\ifnum\appendixno=`I I%
\else\ifnum\appendixno=`J J%
\else\ifnum\appendixno=`K K%
\else\ifnum\appendixno=`L L%
\else\ifnum\appendixno=`M M%
\else\ifnum\appendixno=`N N%
\else\ifnum\appendixno=`O O%
\else\ifnum\appendixno=`P P%
\else\ifnum\appendixno=`Q Q%
\else\ifnum\appendixno=`R R%
\else\ifnum\appendixno=`S S%
\else\ifnum\appendixno=`T T%
\else\ifnum\appendixno=`U U%
\else\ifnum\appendixno=`V V%
\else\ifnum\appendixno=`W W%
\else\ifnum\appendixno=`X X%
\else\ifnum\appendixno=`Y Y%
\else\ifnum\appendixno=`Z Z%
% The \the is necessary, despite appearances, because \appendixletter is
% expanded while writing the .toc file. \char\appendixno is not
% expandable, thus it is written literally, thus all appendixes come out
% with the same letter (or @) in the toc without it.
\else\char\the\appendixno
\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}
% Each @chapter defines these (using marks) as the number+name, number
% and name of the chapter. Page headings and footings can use
% these. @section does likewise.
\def\thischapter{}
\def\thischapternum{}
\def\thischaptername{}
\def\thissection{}
\def\thissectionnum{}
\def\thissectionname{}
\newcount\absseclevel % used to calculate proper heading level
\newcount\secbase\secbase=0 % @raisesections/@lowersections modify this count
% @raisesections: treat @section as chapter, @subsection as section, etc.
\def\raisesections{\global\advance\secbase by -1}
% @lowersections: treat @chapter as section, @section as subsection, etc.
\def\lowersections{\global\advance\secbase by 1}
% we only have subsub.
\chardef\maxseclevel = 3
%
% A numbered section within an unnumbered changes to unnumbered too.
% To achieve this, remember the "biggest" unnum. sec. we are currently in:
\chardef\unnlevel = \maxseclevel
%
% Trace whether the current chapter is an appendix or not:
% \chapheadtype is "N" or "A", unnumbered chapters are ignored.
\def\chapheadtype{N}
% Choose a heading macro
% #1 is heading type
% #2 is heading level
% #3 is text for heading
\def\genhead#1#2#3{%
% Compute the abs. sec. level:
\absseclevel=#2
\advance\absseclevel by \secbase
% Make sure \absseclevel doesn't fall outside the range:
\ifnum \absseclevel < 0
\absseclevel = 0
\else
\ifnum \absseclevel > 3
\absseclevel = 3
\fi
\fi
% The heading type:
\def\headtype{#1}%
\if \headtype U%
\ifnum \absseclevel < \unnlevel
\chardef\unnlevel = \absseclevel
\fi
\else
% Check for appendix sections:
\ifnum \absseclevel = 0
\edef\chapheadtype{\headtype}%
\else
\if \headtype A\if \chapheadtype N%
\errmessage{@appendix... within a non-appendix chapter}%
\fi\fi
\fi
% Check for numbered within unnumbered:
\ifnum \absseclevel > \unnlevel
\def\headtype{U}%
\else
\chardef\unnlevel = 3
\fi
\fi
% Now print the heading:
\if \headtype U%
\ifcase\absseclevel
\unnumberedzzz{#3}%
\or \unnumberedseczzz{#3}%
\or \unnumberedsubseczzz{#3}%
\or \unnumberedsubsubseczzz{#3}%
\fi
\else
\if \headtype A%
\ifcase\absseclevel
\appendixzzz{#3}%
\or \appendixsectionzzz{#3}%
\or \appendixsubseczzz{#3}%
\or \appendixsubsubseczzz{#3}%
\fi
\else
\ifcase\absseclevel
\chapterzzz{#3}%
\or \seczzz{#3}%
\or \numberedsubseczzz{#3}%
\or \numberedsubsubseczzz{#3}%
\fi
\fi
\fi
\suppressfirstparagraphindent
}
% an interface:
\def\numhead{\genhead N}
\def\apphead{\genhead A}
\def\unnmhead{\genhead U}
% @chapter, @appendix, @unnumbered. Increment top-level counter, reset
% all lower-level sectioning counters to zero.
%
% Also set \chaplevelprefix, which we prepend to @float sequence numbers
% (e.g., figures), q.v. By default (before any chapter), that is empty.
\let\chaplevelprefix = \empty
%
\outer\parseargdef\chapter{\numhead0{#1}} % normally numhead0 calls chapterzzz
\def\chapterzzz#1{%
% section resetting is \global in case the chapter is in a group, such
% as an @include file.
\global\secno=0 \global\subsecno=0 \global\subsubsecno=0
\global\advance\chapno by 1
%
% Used for \float.
\gdef\chaplevelprefix{\the\chapno.}%
\resetallfloatnos
%
% \putwordChapter can contain complex things in translations.
\toks0=\expandafter{\putwordChapter}%
\message{\the\toks0 \space \the\chapno}%
%
% Write the actual heading.
\chapmacro{#1}{Ynumbered}{\the\chapno}%
%
% So @section and the like are numbered underneath this chapter.
\global\let\section = \numberedsec
\global\let\subsection = \numberedsubsec
\global\let\subsubsection = \numberedsubsubsec
}
\outer\parseargdef\appendix{\apphead0{#1}} % normally calls appendixzzz
%
\def\appendixzzz#1{%
\global\secno=0 \global\subsecno=0 \global\subsubsecno=0
\global\advance\appendixno by 1
\gdef\chaplevelprefix{\appendixletter.}%
\resetallfloatnos
%
% \putwordAppendix can contain complex things in translations.
\toks0=\expandafter{\putwordAppendix}%
\message{\the\toks0 \space \appendixletter}%
%
\chapmacro{#1}{Yappendix}{\appendixletter}%
%
\global\let\section = \appendixsec
\global\let\subsection = \appendixsubsec
\global\let\subsubsection = \appendixsubsubsec
}
% normally unnmhead0 calls unnumberedzzz:
\outer\parseargdef\unnumbered{\unnmhead0{#1}}
\def\unnumberedzzz#1{%
\global\advance\unnumberedno by 1
%
% Since an unnumbered has no number, no prefix for figures.
\global\let\chaplevelprefix = \empty
\resetallfloatnos
%
% This used to be simply \message{#1}, but TeX fully expands the
% argument to \message. Therefore, if #1 contained @-commands, TeX
% expanded them. For example, in `@unnumbered The @cite{Book}', TeX
% expanded @cite (which turns out to cause errors because \cite is meant
% to be executed, not expanded).
%
% Anyway, we don't want the fully-expanded definition of @cite to appear
% as a result of the \message, we just want `@cite' itself. We use
% \the to achieve this: TeX expands \the only once,
% simply yielding the contents of . (We also do this for
% the toc entries.)
\toks0 = {#1}%
\message{(\the\toks0)}%
%
\chapmacro{#1}{Ynothing}{\the\unnumberedno}%
%
\global\let\section = \unnumberedsec
\global\let\subsection = \unnumberedsubsec
\global\let\subsubsection = \unnumberedsubsubsec
}
% @centerchap is like @unnumbered, but the heading is centered.
\outer\parseargdef\centerchap{%
\let\centerparametersmaybe = \centerparameters
\unnmhead0{#1}%
\let\centerparametersmaybe = \relax
}
% @top is like @unnumbered.
\let\top\unnumbered
% Sections.
%
\outer\parseargdef\numberedsec{\numhead1{#1}} % normally calls seczzz
\def\seczzz#1{%
\global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1
\sectionheading{#1}{sec}{Ynumbered}{\the\chapno.\the\secno}%
}
% normally calls appendixsectionzzz:
\outer\parseargdef\appendixsection{\apphead1{#1}}
\def\appendixsectionzzz#1{%
\global\subsecno=0 \global\subsubsecno=0 \global\advance\secno by 1
\sectionheading{#1}{sec}{Yappendix}{\appendixletter.\the\secno}%
}
\let\appendixsec\appendixsection
% normally calls unnumberedseczzz:
\outer\parseargdef\unnumberedsec{\unnmhead1{#1}}
\def\unnumberedseczzz#1{%
\global\advance\unnumberedno by 1
\sectionheading{#1}{sec}{Ynothing}{\the\unnumberedno}%
}
% Subsections.
%
% normally calls numberedsubseczzz:
\outer\parseargdef\numberedsubsec{\numhead2{#1}}
\def\numberedsubseczzz#1{%
\global\subsubsecno=0 \global\advance\subsecno by 1
\sectionheading{#1}{subsec}{Ynumbered}{\the\chapno.\the\secno.\the\subsecno}%
}
% normally calls appendixsubseczzz:
\outer\parseargdef\appendixsubsec{\apphead2{#1}}
\def\appendixsubseczzz#1{%
\global\subsubsecno=0 \global\advance\subsecno by 1
\sectionheading{#1}{subsec}{Yappendix}%
{\appendixletter.\the\secno.\the\subsecno}%
}
% normally calls unnumberedsubseczzz:
\outer\parseargdef\unnumberedsubsec{\unnmhead2{#1}}
\def\unnumberedsubseczzz#1{%
\global\advance\unnumberedno by 1
\sectionheading{#1}{subsec}{Ynothing}{\the\unnumberedno}%
}
% Subsubsections.
%
% normally numberedsubsubseczzz:
\outer\parseargdef\numberedsubsubsec{\numhead3{#1}}
\def\numberedsubsubseczzz#1{%
\global\advance\subsubsecno by 1
\sectionheading{#1}{subsubsec}{Ynumbered}%
{\the\chapno.\the\secno.\the\subsecno.\the\subsubsecno}%
}
% normally appendixsubsubseczzz:
\outer\parseargdef\appendixsubsubsec{\apphead3{#1}}
\def\appendixsubsubseczzz#1{%
\global\advance\subsubsecno by 1
\sectionheading{#1}{subsubsec}{Yappendix}%
{\appendixletter.\the\secno.\the\subsecno.\the\subsubsecno}%
}
% normally unnumberedsubsubseczzz:
\outer\parseargdef\unnumberedsubsubsec{\unnmhead3{#1}}
\def\unnumberedsubsubseczzz#1{%
\global\advance\unnumberedno by 1
\sectionheading{#1}{subsubsec}{Ynothing}{\the\unnumberedno}%
}
% These macros control what the section commands do, according
% to what kind of chapter we are in (ordinary, appendix, or unnumbered).
% Define them by default for a numbered chapter.
\let\section = \numberedsec
\let\subsection = \numberedsubsec
\let\subsubsection = \numberedsubsubsec
% Define @majorheading, @heading and @subheading
\def\majorheading{%
{\advance\chapheadingskip by 10pt \chapbreak }%
\parsearg\chapheadingzzz
}
\def\chapheading{\chapbreak \parsearg\chapheadingzzz}
\def\chapheadingzzz#1{%
\vbox{\chapfonts \raggedtitlesettings #1\par}%
\nobreak\bigskip \nobreak
\suppressfirstparagraphindent
}
% @heading, @subheading, @subsubheading.
\parseargdef\heading{\sectionheading{#1}{sec}{Yomitfromtoc}{}
\suppressfirstparagraphindent}
\parseargdef\subheading{\sectionheading{#1}{subsec}{Yomitfromtoc}{}
\suppressfirstparagraphindent}
\parseargdef\subsubheading{\sectionheading{#1}{subsubsec}{Yomitfromtoc}{}
\suppressfirstparagraphindent}
% These macros generate a chapter, section, etc. heading only
% (including whitespace, linebreaking, etc. around it),
% given all the information in convenient, parsed form.
% Args are the skip and penalty (usually negative)
\def\dobreak#1#2{\par\ifdim\lastskip<#1\removelastskip\penalty#2\vskip#1\fi}
% Parameter controlling skip before chapter headings (if needed)
\newskip\chapheadingskip
% Define plain chapter starts, and page on/off switching for it.
\def\chapbreak{\dobreak \chapheadingskip {-4000}}
% Start a new page
\def\chappager{\par\vfill\supereject}
% \chapoddpage - start on an odd page for a new chapter
% Because \domark is called before \chapoddpage, the filler page will
% get the headings for the next chapter, which is wrong. But we don't
% care -- we just disable all headings on the filler page.
\def\chapoddpage{%
\chappager
\ifodd\pageno \else
\begingroup
\headingsoff
\null
\chappager
\endgroup
\fi
}
\parseargdef\setchapternewpage{\csname CHAPPAG#1\endcsname\HEADINGSon}
\def\CHAPPAGoff{%
\global\let\contentsalignmacro = \chappager
\global\let\pchapsepmacro=\chapbreak
\global\def\HEADINGSon{\HEADINGSsinglechapoff}}
\def\CHAPPAGon{%
\global\let\contentsalignmacro = \chappager
\global\let\pchapsepmacro=\chappager
\global\def\HEADINGSon{\HEADINGSsingle}}
\def\CHAPPAGodd{%
\global\let\contentsalignmacro = \chapoddpage
\global\let\pchapsepmacro=\chapoddpage
\global\def\HEADINGSon{\HEADINGSdouble}}
\setchapternewpage on
% \chapmacro - Chapter opening.
%
% #1 is the text, #2 is the section type (Ynumbered, Ynothing,
% Yappendix, Yomitfromtoc), #3 the chapter number.
% Not used for @heading series.
%
% To test against our argument.
\def\Ynothingkeyword{Ynothing}
\def\Yappendixkeyword{Yappendix}
\def\Yomitfromtockeyword{Yomitfromtoc}
%
%
% Definitions for @thischapter. These can be overridden in translation
% files.
\def\thischapterAppendix{%
\putwordAppendix{} \thischapternum: \thischaptername}
\def\thischapterChapter{%
\putwordChapter{} \thischapternum: \thischaptername}
%
%
\def\chapmacro#1#2#3{%
\expandafter\ifx\thisenv\titlepage\else
\checkenv{}% chapters, etc., should not start inside an environment.
\fi
% Insert the first mark before the heading break (see notes for \domark).
\let\prevchapterdefs=\currentchapterdefs
\let\prevsectiondefs=\currentsectiondefs
\gdef\currentsectiondefs{\gdef\thissectionname{}\gdef\thissectionnum{}%
\gdef\thissection{}}%
%
\def\temptype{#2}%
\ifx\temptype\Ynothingkeyword
\gdef\currentchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}%
\gdef\thischapter{\thischaptername}}%
\else\ifx\temptype\Yomitfromtockeyword
\gdef\currentchapterdefs{\gdef\thischaptername{#1}\gdef\thischapternum{}%
\gdef\thischapter{}}%
\else\ifx\temptype\Yappendixkeyword
\toks0={#1}%
\xdef\currentchapterdefs{%
\gdef\noexpand\thischaptername{\the\toks0}%
\gdef\noexpand\thischapternum{\appendixletter}%
\let\noexpand\thischapter\noexpand\thischapterAppendix
}%
\else
\toks0={#1}%
\xdef\currentchapterdefs{%
\gdef\noexpand\thischaptername{\the\toks0}%
\gdef\noexpand\thischapternum{\the\chapno}%
\let\noexpand\thischapter\noexpand\thischapterChapter
}%
\fi\fi\fi
%
% Output the mark. Pass it through \safewhatsit, to take care of
% the preceding space.
\safewhatsit\domark
%
% Insert the chapter heading break.
\pchapsepmacro
%
% Now the second mark, after the heading break. No break points
% between here and the heading.
\let\prevchapterdefs=\currentchapterdefs
\let\prevsectiondefs=\currentsectiondefs
\domark
%
{%
\chapfonts \rm
\let\footnote=\errfootnoteheading % give better error message
%
% Have to define \currentsection before calling \donoderef, because the
% xref code eventually uses it. On the other hand, it has to be called
% after \pchapsepmacro, or the headline will change too soon.
\gdef\currentsection{#1}%
%
% Only insert the separating space if we have a chapter/appendix
% number, and don't print the unnumbered ``number''.
\ifx\temptype\Ynothingkeyword
\setbox0 = \hbox{}%
\def\toctype{unnchap}%
\else\ifx\temptype\Yomitfromtockeyword
\setbox0 = \hbox{}% contents like unnumbered, but no toc entry
\def\toctype{omit}%
\else\ifx\temptype\Yappendixkeyword
\setbox0 = \hbox{\putwordAppendix{} #3\enspace}%
\def\toctype{app}%
\else
\setbox0 = \hbox{#3\enspace}%
\def\toctype{numchap}%
\fi\fi\fi
%
% Write the toc entry for this chapter. Must come before the
% \donoderef, because we include the current node name in the toc
% entry, and \donoderef resets it to empty.
\writetocentry{\toctype}{#1}{#3}%
%
% For pdftex, we have to write out the node definition (aka, make
% the pdfdest) after any page break, but before the actual text has
% been typeset. If the destination for the pdf outline is after the
% text, then jumping from the outline may wind up with the text not
% being visible, for instance under high magnification.
\donoderef{#2}%
%
% Typeset the actual heading.
\nobreak % Avoid page breaks at the interline glue.
\vbox{\raggedtitlesettings \hangindent=\wd0 \centerparametersmaybe
\unhbox0 #1\par}%
}%
\nobreak\bigskip % no page break after a chapter title
\nobreak
}
% @centerchap -- centered and unnumbered.
\let\centerparametersmaybe = \relax
\def\centerparameters{%
\advance\rightskip by 3\rightskip
\leftskip = \rightskip
\parfillskip = 0pt
}
% Section titles. These macros combine the section number parts and
% call the generic \sectionheading to do the printing.
%
\newskip\secheadingskip
\def\secheadingbreak{\dobreak \secheadingskip{-1000}}
% Subsection titles.
\newskip\subsecheadingskip
\def\subsecheadingbreak{\dobreak \subsecheadingskip{-500}}
% Subsubsection titles.
\def\subsubsecheadingskip{\subsecheadingskip}
\def\subsubsecheadingbreak{\subsecheadingbreak}
% Definition for @thissection. This can be overridden in translation
% files.
\def\thissectionDef{%
\putwordSection{} \thissectionnum: \thissectionname}
%
% Print any size, any type, section title.
%
% #1 is the text of the title,
% #2 is the section level (sec/subsec/subsubsec),
% #3 is the section type (Ynumbered, Ynothing, Yappendix, Yomitfromtoc),
% #4 is the section number.
%
\def\seckeyword{sec}
%
\def\sectionheading#1#2#3#4{%
{%
\def\sectionlevel{#2}%
\def\temptype{#3}%
%
% It is ok for the @heading series commands to appear inside an
% environment (it's been historically allowed, though the logic is
% dubious), but not the others.
\ifx\temptype\Yomitfromtockeyword\else
\checkenv{}% non-@*heading should not be in an environment.
\fi
\let\footnote=\errfootnoteheading
%
% Switch to the right set of fonts.
\csname #2fonts\endcsname \rm
%
% Insert first mark before the heading break (see notes for \domark).
\let\prevsectiondefs=\currentsectiondefs
\ifx\temptype\Ynothingkeyword
\ifx\sectionlevel\seckeyword
\gdef\currentsectiondefs{\gdef\thissectionname{#1}\gdef\thissectionnum{}%
\gdef\thissection{\thissectionname}}%
\fi
\else\ifx\temptype\Yomitfromtockeyword
% Don't redefine \thissection.
\else\ifx\temptype\Yappendixkeyword
\ifx\sectionlevel\seckeyword
\toks0={#1}%
\xdef\currentsectiondefs{%
\gdef\noexpand\thissectionname{\the\toks0}%
\gdef\noexpand\thissectionnum{#4}%
\let\noexpand\thissection\noexpand\thissectionDef
}%
\fi
\else
\ifx\sectionlevel\seckeyword
\toks0={#1}%
\xdef\currentsectiondefs{%
\gdef\noexpand\thissectionname{\the\toks0}%
\gdef\noexpand\thissectionnum{#4}%
\let\noexpand\thissection\noexpand\thissectionDef
}%
\fi
\fi\fi\fi
%
% Go into vertical mode. Usually we'll already be there, but we
% don't want the following whatsit to end up in a preceding paragraph
% if the document didn't happen to have a blank line.
\par
%
% Output the mark. Pass it through \safewhatsit, to take care of
% the preceding space.
\safewhatsit\domark
%
% Insert space above the heading.
\csname #2headingbreak\endcsname
%
% Now the second mark, after the heading break. No break points
% between here and the heading.
\global\let\prevsectiondefs=\currentsectiondefs
\domark
%
% Only insert the space after the number if we have a section number.
\ifx\temptype\Ynothingkeyword
\setbox0 = \hbox{}%
\def\toctype{unn}%
\gdef\currentsection{#1}%
\else\ifx\temptype\Yomitfromtockeyword
% for @headings -- no section number, don't include in toc,
% and don't redefine \currentsection.
\setbox0 = \hbox{}%
\def\toctype{omit}%
\let\sectionlevel=\empty
\else\ifx\temptype\Yappendixkeyword
\setbox0 = \hbox{#4\enspace}%
\def\toctype{app}%
\gdef\currentsection{#1}%
\else
\setbox0 = \hbox{#4\enspace}%
\def\toctype{num}%
\gdef\currentsection{#1}%
\fi\fi\fi
%
% Write the toc entry (before \donoderef). See comments in \chapmacro.
\writetocentry{\toctype\sectionlevel}{#1}{#4}%
%
% Write the node reference (= pdf destination for pdftex).
% Again, see comments in \chapmacro.
\donoderef{#3}%
%
% Interline glue will be inserted when the vbox is completed.
% That glue will be a valid breakpoint for the page, since it'll be
% preceded by a whatsit (usually from the \donoderef, or from the
% \writetocentry if there was no node). We don't want to allow that
% break, since then the whatsits could end up on page n while the
% section is on page n+1, thus toc/etc. are wrong. Debian bug 276000.
\nobreak
%
% Output the actual section heading.
\vbox{\hyphenpenalty=10000 \tolerance=5000 \parindent=0pt \ptexraggedright
\hangindent=\wd0 % zero if no section number
\unhbox0 #1}%
}%
% Add extra space after the heading -- half of whatever came above it.
% Don't allow stretch, though.
\kern .5 \csname #2headingskip\endcsname
%
% Do not let the kern be a potential breakpoint, as it would be if it
% was followed by glue.
\nobreak
%
% We'll almost certainly start a paragraph next, so don't let that
% glue accumulate. (Not a breakpoint because it's preceded by a
% discardable item.) However, when a paragraph is not started next
% (\startdefun, \cartouche, \center, etc.), this needs to be wiped out
% or the negative glue will cause weirdly wrong output, typically
% obscuring the section heading with something else.
\vskip-\parskip
%
% This is so the last item on the main vertical list is a known
% \penalty > 10000, so \startdefun, etc., can recognize the situation
% and do the needful.
\penalty 10001
}
\message{toc,}
% Table of contents.
\newwrite\tocfile
% Write an entry to the toc file, opening it if necessary.
% Called from @chapter, etc.
%
% Example usage: \writetocentry{sec}{Section Name}{\the\chapno.\the\secno}
% We append the current node name (if any) and page number as additional
% arguments for the \{chap,sec,...}entry macros which will eventually
% read this. The node name is used in the pdf outlines as the
% destination to jump to.
%
% We open the .toc file for writing here instead of at @setfilename (or
% any other fixed time) so that @contents can be anywhere in the document.
% But if #1 is `omit', then we don't do anything. This is used for the
% table of contents chapter openings themselves.
%
\newif\iftocfileopened
\def\omitkeyword{omit}%
%
\def\writetocentry#1#2#3{%
\edef\writetoctype{#1}%
\ifx\writetoctype\omitkeyword \else
\iftocfileopened\else
\immediate\openout\tocfile = \jobname.toc
\global\tocfileopenedtrue
\fi
%
\iflinks
{\atdummies
\edef\temp{%
\write\tocfile{@#1entry{#2}{#3}{\lastnode}{\noexpand\folio}}}%
\temp
}%
\fi
\fi
%
% Tell \shipout to create a pdf destination on each page, if we're
% writing pdf. These are used in the table of contents. We can't
% just write one on every page because the title pages are numbered
% 1 and 2 (the page numbers aren't printed), and so are the first
% two pages of the document. Thus, we'd have two destinations named
% `1', and two named `2'.
\ifpdforxetex
\global\pdfmakepagedesttrue
\fi
}
% These characters do not print properly in the Computer Modern roman
% fonts, so we must take special care. This is more or less redundant
% with the Texinfo input format setup at the end of this file.
%
\def\activecatcodes{%
\catcode`\"=\active
\catcode`\$=\active
\catcode`\<=\active
\catcode`\>=\active
\catcode`\\=\active
\catcode`\^=\active
\catcode`\_=\active
\catcode`\|=\active
\catcode`\~=\active
}
% Read the toc file, which is essentially Texinfo input.
\def\readtocfile{%
\setupdatafile
\activecatcodes
\input \tocreadfilename
}
% process toc file to find the maximum width of the section numbers for
% each chapter
\def\findsecnowidths{%
\begingroup
\setupdatafile
\activecatcodes
\secentryfonts
% Redefinitions
\def\numchapentry##1##2##3##4{%
\def\curchapname{secnowidth-##2}%
\curchapmax=0pt
}%
\let\appentry\numchapentry
%
\def\numsecentry##1##2##3##4{%
\def\cursecname{secnowidth-##2}%
\cursecmax=0pt
%
\setbox0=\hbox{##2}%
\ifdim\wd0>\curchapmax
\curchapmax=\wd0
\expandafter\xdef\csname\curchapname\endcsname{\the\wd0}%
\fi
}%
\let\appsecentry\numsecentry
%
\def\numsubsecentry##1##2##3##4{%
\def\curssecname{secnowidth-##2}%
\curssecmax=0pt
%
\setbox0=\hbox{##2}%
\ifdim\wd0>\cursecmax
\cursecmax=\wd0
\expandafter\xdef\csname\cursecname\endcsname{\the\wd0}%
\fi
}%
\let\appsubsecentry\numsubsecentry
%
\def\numsubsubsecentry##1##2##3##4{%
\setbox0=\hbox{##2}%
\ifdim\wd0>\curssecmax
\curssecmax=\wd0
\expandafter\xdef\csname\curssecname\endcsname{\the\wd0}%
\fi
}%
\let\appsubsubsecentry\numsubsubsecentry
%
% Discard any output by outputting to dummy vbox, in case the toc file
% contains macros that we have not redefined above.
\setbox\dummybox\vbox\bgroup
\input \tocreadfilename\relax
\egroup
\endgroup
}
\newdimen\curchapmax
\newdimen\cursecmax
\newdimen\curssecmax
% set #1 to the maximum section width for #2
\def\retrievesecnowidth#1#2{%
\expandafter\let\expandafter\savedsecnowidth \csname secnowidth-#2\endcsname
\ifx\savedsecnowidth\relax
#1=0pt
\else
#1=\savedsecnowidth
\fi
}
\newdimen\secnowidthchap
\secnowidthchap=0pt
\newdimen\secnowidthsec
\secnowidthsec=0pt
\newdimen\secnowidthssec
\secnowidthssec=0pt
\newskip\contentsrightmargin \contentsrightmargin=1in
\newcount\savepageno
\newcount\lastnegativepageno \lastnegativepageno = -1
% Prepare to read what we've written to \tocfile.
%
\def\startcontents#1{%
% If @setchapternewpage on, and @headings double, the contents should
% start on an odd page, unlike chapters.
\contentsalignmacro
\immediate\closeout\tocfile
%
% Don't need to put `Contents' or `Short Contents' in the headline.
% It is abundantly clear what they are.
\chapmacro{#1}{Yomitfromtoc}{}%
%
\savepageno = \pageno
\begingroup % Set up to handle contents files properly.
\raggedbottom % Worry more about breakpoints than the bottom.
\entryrightmargin=\contentsrightmargin % Don't use the full line length.
%
% Roman numerals for page numbers.
\ifnum \pageno>0 \global\pageno = \lastnegativepageno \fi
\def\thistitle{}% no title in double-sided headings
% Record where the Roman numerals started.
\ifnum\romancount=0 \global\romancount=\pagecount \fi
\linkentrytexttrue
}
% \raggedbottom in plain.tex hardcodes \topskip so override it
\catcode`\@=11
\def\raggedbottom{\advance\topskip by 0pt plus60pt \r@ggedbottomtrue}
\catcode`\@=\other
% redefined for the two-volume lispref. We always output on
% \jobname.toc even if this is redefined.
%
\def\tocreadfilename{\jobname.toc}
% Normal (long) toc.
%
\def\contents{%
\startcontents{\putwordTOC}%
\openin 1 \tocreadfilename\space
\ifeof 1 \else
\findsecnowidths
\readtocfile
\fi
\vfill \eject
\contentsalignmacro % in case @setchapternewpage odd is in effect
\ifeof 1 \else
\pdfmakeoutlines
\fi
\closein 1
\endgroup
\contentsendroman
}
% And just the chapters.
\def\summarycontents{%
\startcontents{\putwordShortTOC}%
%
\let\partentry = \shortpartentry
\let\numchapentry = \shortchapentry
\let\appentry = \shortchapentry
\let\unnchapentry = \shortunnchapentry
% We want a true roman here for the page numbers.
\secfonts
\let\rm=\shortcontrm \let\bf=\shortcontbf
\let\sl=\shortcontsl \let\tt=\shortconttt
\rm
\hyphenpenalty = 10000
\advance\baselineskip by 1pt % Open it up a little.
\extrasecnoskip=0.4pt
\def\numsecentry##1##2##3##4{}
\let\appsecentry = \numsecentry
\let\unnsecentry = \numsecentry
\let\numsubsecentry = \numsecentry
\let\appsubsecentry = \numsecentry
\let\unnsubsecentry = \numsecentry
\let\numsubsubsecentry = \numsecentry
\let\appsubsubsecentry = \numsecentry
\let\unnsubsubsecentry = \numsecentry
\openin 1 \tocreadfilename\space
\ifeof 1 \else
\readtocfile
\fi
\closein 1
\vfill \eject
\contentsalignmacro % in case @setchapternewpage odd is in effect
\endgroup
\contentsendroman
}
\let\shortcontents = \summarycontents
% Get ready to use Arabic numerals again
\def\contentsendroman{%
\lastnegativepageno = \pageno
\global\pageno=1
\contentsendcount = \pagecount
}
% Typeset the label for a chapter or appendix for the short contents.
% The arg is, e.g., `A' for an appendix, or `3' for a chapter.
%
\def\shortchaplabel#1{%
% This space should be enough, since a single number is .5em, and the
% widest letter (M) is 1em, at least in the Computer Modern fonts.
% But use \hss just in case.
%
% We'd like to right-justify chapter numbers, but that looks strange
% with appendix letters. And right-justifying numbers and
% left-justifying letters looks strange when there is less than 10
% chapters. Have to read the whole toc once to know how many chapters
% there are before deciding ...
\hbox to 1em{#1\hss}%
}
% These macros generate individual entries in the table of contents,
% and are read in from the *.toc file.
%
% The arguments are like:
% \def\numchapentry#1#2#3#4
% #1 - the chapter or section name.
% #2 - section number
% #3 - level of section (e.g "chap", "sec")
% #4 - page number
% Parts, in the main contents. Replace the part number, which doesn't
% exist, with an empty box. Let's hope all the numbers have the same width.
% Also ignore the page number, which is conventionally not printed.
\def\numeralbox{\setbox0=\hbox{8}\hbox to \wd0{\hfil}}
\def\partentry#1#2#3#4{%
% Add stretch and a bonus for breaking the page before the part heading.
% This reduces the chance of the page being broken immediately after the
% part heading, before a following chapter heading.
\vskip 0pt plus 5\baselineskip
\penalty-300
\vskip 0pt plus -5\baselineskip
\dochapentry{#1}{\numeralbox}{}%
}
%
% Parts, in the short toc.
\def\shortpartentry#1#2#3#4{%
\penalty-300
\vskip.5\baselineskip plus.15\baselineskip minus.1\baselineskip
\shortchapentry{{\bf #1}}{\numeralbox}{}{}%
}
% Chapters, in the main contents.
\def\numchapentry#1#2#3#4{%
\retrievesecnowidth\secnowidthchap{#2}%
\dochapentry{#1}{#2}{#4}%
}
% Chapters, in the short toc.
\def\shortchapentry#1#2#3#4{%
\tocentry{#1}{\shortchaplabel{#2}}{#4}%
}
% Appendices, in the main contents.
% Need the word Appendix, and a fixed-size box.
%
\def\appendixbox#1{%
% We use M since it's probably the widest letter.
\setbox0 = \hbox{\putwordAppendix{} M}%
\hbox to \wd0{\putwordAppendix{} #1\hss}}
%
\def\appentry#1#2#3#4{%
\retrievesecnowidth\secnowidthchap{#2}%
\dochapentry{\appendixbox{#2}\hskip.7em#1}{}{#4}%
}
% Unnumbered chapters.
\def\unnchapentry#1#2#3#4{\dochapentry{#1}{}{#4}}
\def\shortunnchapentry#1#2#3#4{\tocentry{#1}{}{#4}}
% Sections.
\def\numsecentry#1#2#3#4{\dosecentry{#1}{#2}{#4}}
\def\numsecentry#1#2#3#4{%
\retrievesecnowidth\secnowidthsec{#2}%
\dosecentry{#1}{#2}{#4}%
}
\let\appsecentry=\numsecentry
\def\unnsecentry#1#2#3#4{%
\retrievesecnowidth\secnowidthsec{#2}%
\dosecentry{#1}{}{#4}%
}
% Subsections.
\def\numsubsecentry#1#2#3#4{%
\retrievesecnowidth\secnowidthssec{#2}%
\dosubsecentry{#1}{#2}{#4}%
}
\let\appsubsecentry=\numsubsecentry
\def\unnsubsecentry#1#2#3#4{%
\retrievesecnowidth\secnowidthssec{#2}%
\dosubsecentry{#1}{}{#4}%
}
% And subsubsections.
\def\numsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{#2}{#4}}
\let\appsubsubsecentry=\numsubsubsecentry
\def\unnsubsubsecentry#1#2#3#4{\dosubsubsecentry{#1}{}{#4}}
% This parameter controls the indentation of the various levels.
% Same as \defaultparindent.
\newdimen\tocindent \tocindent = 15pt
% Now for the actual typesetting. In all these, #1 is the text, #2 is
% a section number if present, and #3 is the page number.
%
% If the toc has to be broken over pages, we want it to be at chapters
% if at all possible; hence the \penalty.
\def\dochapentry#1#2#3{%
\penalty-300 \vskip1\baselineskip plus.33\baselineskip minus.25\baselineskip
\begingroup
% Move the page numbers slightly to the right
\advance\entryrightmargin by -0.05em
\chapentryfonts
\extrasecnoskip=0.4em % separate chapter number more
\tocentry{#1}{#2}{#3}%
\endgroup
\nobreak\vskip .25\baselineskip plus.1\baselineskip
}
\def\dosecentry#1#2#3{\begingroup
\secnowidth=\secnowidthchap
\secentryfonts \leftskip=\tocindent
\tocentry{#1}{#2}{#3}%
\endgroup}
\def\dosubsecentry#1#2#3{\begingroup
\secnowidth=\secnowidthsec
\subsecentryfonts \leftskip=2\tocindent
\tocentry{#1}{#2}{#3}%
\endgroup}
\def\dosubsubsecentry#1#2#3{\begingroup
\secnowidth=\secnowidthssec
\subsubsecentryfonts \leftskip=3\tocindent
\tocentry{#1}{#2}{#3}%
\endgroup}
% Used for the maximum width of a section number so we can align
% section titles.
\newdimen\secnowidth
\secnowidth=0pt
\newdimen\extrasecnoskip
\extrasecnoskip=0pt
% \tocentry{TITLE}{SEC NO}{PAGE}
%
\def\tocentry#1#2#3{%
\def\secno{#2}%
\ifx\empty\secno
\entry{#1}{#3}%
\else
\ifdim 0pt=\secnowidth
\setbox0=\hbox{#2\hskip\labelspace\hskip\extrasecnoskip}%
\else
\advance\secnowidth by \labelspace
\advance\secnowidth by \extrasecnoskip
\setbox0=\hbox to \secnowidth{%
#2\hskip\labelspace\hskip\extrasecnoskip\hfill}%
\fi
\entrycontskip=\wd0
\entry{\box0 #1}{#3}%
\fi
}
\newdimen\labelspace
\labelspace=0.6em
\def\chapentryfonts{\secfonts \rm}
\def\secentryfonts{\textfonts}
\def\subsecentryfonts{\textfonts}
\def\subsubsecentryfonts{\textfonts}
\message{environments,}
% @foo ... @end foo.
% @tex ... @end tex escapes into raw TeX temporarily.
% One exception: @ is still an escape character, so that @end tex works.
% But \@ or @@ will get a plain @ character.
\envdef\tex{%
\setregularquotes
\catcode `\\=0 \catcode `\{=1 \catcode `\}=2
\catcode `\$=3 \catcode `\&=4 \catcode `\#=6
\catcode `\^=7 \catcode `\_=8 \catcode `\~=\active \let~=\tie
\catcode `\%=14
\catcode `\+=\other
\catcode `\"=\other
\catcode `\|=\other
\catcode `\<=\other
\catcode `\>=\other
\catcode `\`=\other
\catcode `\'=\other
%
% ' is active in math mode (mathcode"8000). So reset it, and all our
% other math active characters (just in case), to plain's definitions.
\mathactive
%
% Inverse of the list at the beginning of the file.
\let\b=\ptexb
\let\bullet=\ptexbullet
\let\c=\ptexc
\let\,=\ptexcomma
\let\.=\ptexdot
\let\dots=\ptexdots
\let\equiv=\ptexequiv
\let\!=\ptexexclam
\let\i=\ptexi
\let\indent=\ptexindent
\let\noindent=\ptexnoindent
\let\{=\ptexlbrace
\let\+=\tabalign
\let\}=\ptexrbrace
\let\/=\ptexslash
\let\sp=\ptexsp
\let\*=\ptexstar
%\let\sup=\ptexsup % do not redefine, we want @sup to work in math mode
\let\t=\ptext
\expandafter \let\csname top\endcsname=\ptextop % we've made it outer
\let\frenchspacing=\plainfrenchspacing
%
\def\endldots{\mathinner{\ldots\ldots\ldots\ldots}}%
\def\enddots{\relax\ifmmode\endldots\else$\mathsurround=0pt \endldots\,$\fi}%
\def\@{@}%
}
% There is no need to define \Etex.
% Define @lisp ... @end lisp.
% @lisp environment forms a group so it can rebind things,
% including the definition of @end lisp (which normally is erroneous).
% Amount to narrow the margins by for @lisp.
\newskip\lispnarrowing \lispnarrowing=0.4in
% This is the definition that ^^M gets inside @lisp, @example, and other
% such environments. \null is better than a space, since it doesn't
% have any width.
\def\lisppar{\null\endgraf}
% This space is always present above and below environments.
\newskip\envskipamount \envskipamount = 0pt
% Make spacing and below environment symmetrical. We use \parskip here
% to help in doing that, since in @example-like environments \parskip
% is reset to zero; thus the \afterenvbreak inserts no space -- but the
% start of the next paragraph will insert \parskip.
%
\def\aboveenvbreak{{%
% =10000 instead of <10000 because of a special case in \itemzzz and
% \sectionheading, q.v.
\ifnum \lastpenalty=10000 \else
\advance\envskipamount by \parskip
\endgraf
\ifdim\lastskip<\envskipamount
\removelastskip
\ifnum\lastpenalty<10000
% Penalize breaking before the environment, because preceding text
% often leads into it.
\penalty100
\fi
\vskip\envskipamount
\fi
\fi
}}
\def\afterenvbreak{{%
% =10000 instead of <10000 because of a special case in \itemzzz and
% \sectionheading, q.v.
\ifnum \lastpenalty=10000 \else
\advance\envskipamount by \parskip
\endgraf
\ifdim\lastskip<\envskipamount
\removelastskip
% it's not a good place to break if the last penalty was \nobreak
% or better ...
\ifnum\lastpenalty<10000 \penalty-50 \fi
\vskip\envskipamount
\fi
\fi
}}
% \nonarrowing is a flag. If "set", @lisp etc don't narrow margins; it will
% also clear it, so that its embedded environments do the narrowing again.
\let\nonarrowing=\relax
% @cartouche ... @end cartouche: draw rectangle w/rounded corners around
% environment contents.
%
\def\ctl{{\circle\char'013\hskip -6pt}}% 6pt from pl file: 1/2charwidth
\def\ctr{{\hskip 6pt\circle\char'010}}
\def\cbl{{\circle\char'012\hskip -6pt}}
\def\cbr{{\hskip 6pt\circle\char'011}}
\def\carttop{\hbox to \cartouter{\hskip\lskip
\ctl\leaders\hrule height\circthick\hfil\ctr
\hskip\rskip}}
\def\cartbot{\hbox to \cartouter{\hskip\lskip
\cbl\leaders\hrule height\circthick\hfil\cbr
\hskip\rskip}}
%
\newskip\lskip\newskip\rskip
% only require the font if @cartouche is actually used
\def\cartouchefontdefs{%
\font\circle=lcircle10\relax
\circthick=\fontdimen8\circle
}
\newdimen\circthick
\newdimen\cartouter\newdimen\cartinner
\newskip\normbskip\newskip\normpskip\newskip\normlskip
\envparseargdef\cartouche{%
\cartouchefontdefs
\ifhmode\par\fi % can't be in the midst of a paragraph.
\startsavinginserts
\lskip=\leftskip \rskip=\rightskip
\leftskip=0pt\rightskip=0pt % we want these *outside*.
%
% Set paragraph width for text inside cartouche. There are
% left and right margins of 3pt each plus two vrules 0.4pt each.
\cartinner=\hsize \advance\cartinner by-\lskip
\advance\cartinner by-\rskip
\advance\cartinner by -6.8pt
%
% For drawing top and bottom of cartouche. Each corner char
% adds 6pt and we take off the width of a rule to line up with the
% right boundary perfectly.
\cartouter=\hsize
\advance\cartouter by 11.6pt
%
\normbskip=\baselineskip \normpskip=\parskip \normlskip=\lineskip
%
% If this cartouche directly follows a sectioning command, we need the
% \parskip glue (backspaced over by default) or the cartouche can
% collide with the section heading.
\ifnum\lastpenalty>10000 \vskip\parskip \penalty\lastpenalty \fi
%
\setbox\groupbox=\vtop\bgroup
\baselineskip=0pt\parskip=0pt\lineskip=0pt
\carttop
\hbox\bgroup
\hskip\lskip
\vrule\kern3pt
\vbox\bgroup
\hsize=\cartinner
\baselineskip=\normbskip
\lineskip=\normlskip
\parskip=\normpskip
\def\arg{#1}%
\ifx\arg\empty\else
\centerV{\hfil \bf #1 \hfil}%
\fi
\kern3pt
\vskip -\parskip
}
\def\Ecartouche{%
\ifhmode\par\fi
\kern3pt
\egroup
\kern3pt\vrule
\hskip\rskip
\egroup
\cartbot
\egroup
\addgroupbox
\checkinserts
}
% This macro is called at the beginning of all the @example variants,
% inside a group.
\newdimen\nonfillparindent
\def\nonfillstart{%
\aboveenvbreak
\ifdim\hfuzz < 12pt \hfuzz = 12pt \fi % Don't be fussy
\sepspaces % Make spaces be word-separators rather than space tokens.
\let\par = \lisppar % don't ignore blank lines
\obeylines % each line of input is a line of output
\parskip = 0pt
% Turn off paragraph indentation but redefine \indent to emulate
% the normal \indent.
\nonfillparindent=\parindent
\parindent = 0pt
\let\indent\nonfillindent
%
\emergencystretch = 0pt % don't try to avoid overfull boxes
\ifx\nonarrowing\relax
\advance \leftskip by \lispnarrowing
\exdentamount=\lispnarrowing
\else
\let\nonarrowing = \relax
\fi
\let\exdent=\nofillexdent
}
\begingroup
\obeyspaces
% We want to swallow spaces (but not other tokens) after the fake
% @indent in our nonfill-environments, where spaces are normally
% active and set to @tie, resulting in them not being ignored after
% @indent.
\gdef\nonfillindent{\futurelet\temp\nonfillindentcheck}%
\gdef\nonfillindentcheck{%
\ifx\temp %
\expandafter\nonfillindentgobble%
\else%
\leavevmode\nonfillindentbox%
\fi%
}%
\endgroup
\def\nonfillindentgobble#1{\nonfillindent}
\def\nonfillindentbox{\hbox to \nonfillparindent{\hss}}
% If you want all examples etc. small: @set dispenvsize small.
% If you want even small examples the full size: @set dispenvsize nosmall.
% This affects the following displayed environments:
% @example, @display, @format, @lisp, @verbatim
%
\def\smallword{small}
\def\nosmallword{nosmall}
\let\SETdispenvsize\relax
\def\setnormaldispenv{%
\ifx\SETdispenvsize\smallword
% end paragraph for sake of leading, in case document has no blank
% line. This is redundant with what happens in \aboveenvbreak, but
% we need to do it before changing the fonts, and it's inconvenient
% to change the fonts afterward.
\ifnum \lastpenalty=10000 \else \endgraf \fi
\smallexamplefonts \rm
\fi
}
\def\setsmalldispenv{%
\ifx\SETdispenvsize\nosmallword
\else
\ifnum \lastpenalty=10000 \else \endgraf \fi
\smallexamplefonts \rm
\fi
}
% We often define two environments, @foo and @smallfoo.
% Let's do it in one command. #1 is the env name, #2 the definition.
\def\makedispenvdef#1#2{%
\expandafter\envdef\csname#1\endcsname {\setnormaldispenv #2}%
\expandafter\envdef\csname small#1\endcsname {\setsmalldispenv #2}%
\expandafter\let\csname E#1\endcsname \afterenvbreak
\expandafter\let\csname Esmall#1\endcsname \afterenvbreak
}
% Define two environment synonyms (#1 and #2) for an environment.
\def\maketwodispenvdef#1#2#3{%
\makedispenvdef{#1}{#3}%
\makedispenvdef{#2}{#3}%
}
%
% @lisp: indented, narrowed, typewriter font;
% @example: same as @lisp.
%
% @smallexample and @smalllisp: use smaller fonts.
% Originally contributed by Pavel@xerox.
%
\maketwodispenvdef{lisp}{example}{%
\nonfillstart
\tt\setcodequotes
\let\kbdfont = \kbdexamplefont % Allow @kbd to do something special.
\parsearg\gobble
}
% @display/@smalldisplay: same as @lisp except keep current font.
%
\makedispenvdef{display}{%
\nonfillstart
\gobble
}
% @format/@smallformat: same as @display except don't narrow margins.
%
\makedispenvdef{format}{%
\let\nonarrowing = t%
\nonfillstart
\gobble
}
% @flushleft: same as @format, but doesn't obey \SETdispenvsize.
\envdef\flushleft{%
\let\nonarrowing = t%
\nonfillstart
\gobble
}
\let\Eflushleft = \afterenvbreak
% @flushright.
%
\envdef\flushright{%
\let\nonarrowing = t%
\nonfillstart
\advance\leftskip by 0pt plus 1fill\relax
\gobble
}
\let\Eflushright = \afterenvbreak
% @raggedright does more-or-less normal line breaking but no right
% justification. From plain.tex.
\envdef\raggedright{%
\rightskip0pt plus2.4em \spaceskip.3333em \xspaceskip.5em\relax
}
\let\Eraggedright\par
% @quotation does normal linebreaking (hence we can't use \nonfillstart)
% and narrows the margins. We keep \parskip nonzero in general, since
% we're doing normal filling. So, when using \aboveenvbreak and
% \afterenvbreak, temporarily make \parskip 0.
%
\makedispenvdef{quotation}{\quotationstart}
%
\def\quotationstart{%
\indentedblockstart % same as \indentedblock, but increase right margin too.
\ifx\nonarrowing\relax
\advance\rightskip by \lispnarrowing
\fi
\parsearg\quotationlabel
}
% We have retained a nonzero parskip for the environment, since we're
% doing normal filling.
%
\def\Equotation{%
\par
\ifx\quotationauthor\thisisundefined\else
% indent a bit.
\leftline{\kern 2\leftskip \sl ---\quotationauthor}%
\fi
{\parskip=0pt \afterenvbreak}%
}
\def\Esmallquotation{\Equotation}
% If we're given an argument, typeset it in bold with a colon after.
\def\quotationlabel#1{%
\def\temp{#1}%
\ifx\temp\empty \else
{\bf #1: }%
\fi
}
% @indentedblock is like @quotation, but indents only on the left and
% has no optional argument.
%
\makedispenvdef{indentedblock}{\indentedblockstart}
%
\def\indentedblockstart{%
{\parskip=0pt \aboveenvbreak}% because \aboveenvbreak inserts \parskip
\parindent=0pt
%
% @cartouche defines \nonarrowing to inhibit narrowing at next level down.
\ifx\nonarrowing\relax
\advance\leftskip by \lispnarrowing
\exdentamount = \lispnarrowing
\else
\let\nonarrowing = \relax
\fi
}
% Keep a nonzero parskip for the environment, since we're doing normal filling.
%
\def\Eindentedblock{%
\par
{\parskip=0pt \afterenvbreak}%
}
\def\Esmallindentedblock{\Eindentedblock}
% LaTeX-like @verbatim...@end verbatim and @verb{...}
% If we want to allow any as delimiter,
% we need the curly braces so that makeinfo sees the @verb command, eg:
% `@verbx...x' would look like the '@verbx' command. --janneke@gnu.org
%
% [Knuth]: Donald Ervin Knuth, 1996. The TeXbook.
%
% [Knuth] p.344; only we need to do the other characters Texinfo sets
% active too. Otherwise, they get lost as the first character on a
% verbatim line.
\def\dospecials{%
\do\ \do\\\do\{\do\}\do\$\do\&%
\do\#\do\^\do\^^K\do\_\do\^^A\do\%\do\~%
\do\<\do\>\do\|\do\@\do+\do\"%
% Don't do the quotes -- if we do, @set txicodequoteundirected and
% @set txicodequotebacktick will not have effect on @verb and
% @verbatim, and ?` and !` ligatures won't get disabled.
%\do\`\do\'%
}
%
% [Knuth] p. 380
\def\uncatcodespecials{%
\def\do##1{\catcode`##1=\other}\dospecials}
%
% Setup for the @verb command.
%
% Eight spaces for a tab
\begingroup
\catcode`\^^I=\active
\gdef\tabeightspaces{\catcode`\^^I=\active\def^^I{\ \ \ \ \ \ \ \ }}
\endgroup
%
\def\setupverb{%
\tt
\def\par{\leavevmode\endgraf}%
\parindent = 0pt
\setcodequotes
\tabeightspaces
% Respect line breaks,
% print special symbols as themselves, and
% make each space count
% must do in this order:
\obeylines \uncatcodespecials \sepspaces
}
% Setup for the @verbatim environment
%
% Real tab expansion.
\newdimen\tabw \setbox0=\hbox{\tt\space} \tabw=8\wd0 % tab amount
%
% We typeset each line of the verbatim in an \hbox, so we can handle
% tabs.
\newbox\verbbox
\def\starttabbox{\setbox\verbbox=\hbox\bgroup}
%
\begingroup
\catcode`\^^I=\active
\gdef\tabexpand{%
\catcode`\^^I=\active
\def^^I{\leavevmode\egroup
\dimen\verbbox=\wd\verbbox % the width so far, or since the previous tab
\divide\dimen\verbbox by\tabw
\multiply\dimen\verbbox by\tabw % compute previous multiple of \tabw
\advance\dimen\verbbox by\tabw % advance to next multiple of \tabw
\wd\verbbox=\dimen\verbbox
\leavevmode\box\verbbox \starttabbox
}%
}
\endgroup
% start the verbatim environment.
\def\setupverbatim{%
\let\nonarrowing = t%
\nonfillstart
\tt % easiest (and conventionally used) font for verbatim
\def\par{\egroup\leavevmode\box\verbbox\endgraf\starttabbox}%
\tabexpand
\setcodequotes
% Respect line breaks,
% print special symbols as themselves, and
% make each space count.
% Must do in this order:
\obeylines \uncatcodespecials \sepspaces
}
% Do the @verb magic: verbatim text is quoted by unique
% delimiter characters. Before first delimiter expect a
% right brace, after last delimiter expect closing brace:
%
% \def\doverb'{'#1'}'{#1}
%
% [Knuth] p. 382; only eat outer {}
\begingroup
\catcode`[=1\catcode`]=2\catcode`\{=\other\catcode`\}=\other
\gdef\doverb{#1[\def\next##1#1}[##1\endgroup]\next]
\endgroup
%
\def\verb{\begingroup\setupverb\doverb}
%
%
% Do the @verbatim magic: define the macro \doverbatim so that
% the (first) argument ends when '@end verbatim' is reached, ie:
%
% \def\doverbatim#1@end verbatim{#1}
%
% For Texinfo it's a lot easier than for LaTeX,
% because texinfo's \verbatim doesn't stop at '\end{verbatim}':
% we need not redefine '\', '{' and '}'.
%
% Inspired by LaTeX's verbatim command set [latex.ltx]
%
\begingroup
\catcode`\ =\active
\obeylines %
% ignore everything up to the first ^^M, that's the newline at the end
% of the @verbatim input line itself. Otherwise we get an extra blank
% line in the output.
\xdef\doverbatim#1^^M#2@end verbatim{%
\starttabbox#2\egroup\noexpand\end\gobble verbatim}%
% We really want {...\end verbatim} in the body of the macro, but
% without the active space; thus we have to use \xdef and \gobble.
% The \egroup ends the \verbbox started at the end of the last line in
% the block.
\endgroup
%
\envdef\verbatim{%
\setnormaldispenv\setupverbatim\doverbatim
}
\let\Everbatim = \afterenvbreak
% @verbatiminclude FILE - insert text of file in verbatim environment.
%
\def\verbatiminclude{\parseargusing\filenamecatcodes\doverbatiminclude}
%
\def\doverbatiminclude#1{%
{%
\makevalueexpandable
\setupverbatim
{%
\indexnofonts % Allow `@@' and other weird things in file names.
\wlog{texinfo.tex: doing @verbatiminclude of #1^^J}%
\edef\tmp{\noexpand\input #1 }
\expandafter
}\expandafter\starttabbox\tmp\egroup
\afterenvbreak
}%
}
% @copying ... @end copying.
% Save the text away for @insertcopying later.
%
% We save the uninterpreted tokens, rather than creating a box.
% Saving the text in a box would be much easier, but then all the
% typesetting commands (@smallbook, font changes, etc.) have to be done
% beforehand -- and a) we want @copying to be done first in the source
% file; b) letting users define the frontmatter in as flexible order as
% possible is desirable.
%
\def\copying{\checkenv{}\begingroup\macrobodyctxt\docopying}
{\catcode`\ =\other
\gdef\docopying#1@end copying{\endgroup\def\copyingtext{#1}}
}
\def\insertcopying{%
\begingroup
\parindent = 0pt % paragraph indentation looks wrong on title page
\scanexp\copyingtext
\endgroup
}
\message{defuns,}
% @defun etc.
\newskip\defbodyindent \defbodyindent=.4in
\newskip\defargsindent \defargsindent=50pt
\newskip\deflastargmargin \deflastargmargin=18pt
\newcount\defunpenalty
% Start the processing of @deffn:
\def\startdefun{%
\ifnum\lastpenalty<10000
\medbreak
\defunpenalty=10003 % Will keep this @deffn together with the
% following @def command, see below.
\else
% If there are two @def commands in a row, we'll have a \nobreak,
% which is there to keep the function description together with its
% header. But if there's nothing but headers, we need to allow a
% break somewhere. Check specifically for penalty 10002, inserted
% by \printdefunline, instead of 10000, since the sectioning
% commands also insert a nobreak penalty, and we don't want to allow
% a break between a section heading and a defun.
%
% As a further refinement, we avoid "club" headers by signalling
% with penalty of 10003 after the very first @deffn in the
% sequence (see above), and penalty of 10002 after any following
% @def command.
\ifnum\lastpenalty=10002 \penalty2000 \else \defunpenalty=10002 \fi
%
% Similarly, after a section heading, do not allow a break.
% But do insert the glue.
\medskip % preceded by discardable penalty, so not a breakpoint
\fi
%
\parindent=0in
\advance\leftskip by \defbodyindent
\exdentamount=\defbodyindent
}
% Called as \printdefunline \deffooheader{text}
%
\def\printdefunline#1#2{%
\begingroup
\plainfrenchspacing
% call \deffooheader:
#1#2 \endheader
% common ending:
\interlinepenalty = 10000
\advance\rightskip by 0pt plus 1fil\relax
\endgraf
\nobreak\vskip -\parskip
\penalty\defunpenalty % signal to \startdefun and \deffoox
% Some of the @defun-type tags do not enable magic parentheses,
% rendering the following check redundant. But we don't optimize.
\checkparencounts
\endgroup
}
\def\Edefun{\endgraf\medbreak}
% @defblock, @defline do not automatically create index entries
\envdef\defblock{%
\startdefun
}
\let\Edefblock\Edefun
\def\defline{%
\doingtypefnfalse
\parseargusing\activeparens{\printdefunline\deflineheader}%
}
\def\deflineheader#1 #2 #3\endheader{%
\printdefname{#1}{}{#2}\magicamp\defunargs{#3\unskip}%
}
\def\deftypeline{%
\doingtypefntrue
\parseargusing\activeparens{\printdefunline\deftypelineheader}%
}
\def\deftypelineheader#1 #2 #3 #4\endheader{%
\printdefname{#1}{#2}{#3}\magicamp\defunargs{#4\unskip}%
}
% \makedefun{deffoo} (\deffooheader parameters) { (\deffooheader expansion) }
%
% Define \deffoo, \deffoox \Edeffoo and \deffooheader.
\def\makedefun#1{%
\expandafter\let\csname E#1\endcsname = \Edefun
\edef\temp{\noexpand\domakedefun
\makecsname{#1}\makecsname{#1x}\makecsname{#1header}}%
\temp
}
\def\domakedefun#1#2#3{%
\envdef#1{%
\startdefun
\doingtypefnfalse % distinguish typed functions from all else
\parseargusing\activeparens{\printdefunline#3}%
}%
\def#2{%
% First, check whether we are in the right environment:
\checkenv#1%
%
% As in \startdefun, allow line break if we have multiple x headers
% in a row. It's not a great place, though.
\ifnum\lastpenalty=10002 \penalty3000 \else \defunpenalty=10002 \fi
%
\doingtypefnfalse % distinguish typed functions from all else
\parseargusing\activeparens{\printdefunline#3}%
}%
\def#3% definition of \deffooheader follows
}
\newif\ifdoingtypefn % doing typed function?
\newif\ifrettypeownline % typeset return type on its own line?
% @deftypefnnewline on|off says whether the return type of typed functions
% are printed on their own line. This affects @deftypefn, @deftypefun,
% @deftypeop, and @deftypemethod.
%
\parseargdef\deftypefnnewline{%
\def\temp{#1}%
\ifx\temp\onword
\expandafter\let\csname SETtxideftypefnnl\endcsname
= \empty
\else\ifx\temp\offword
\expandafter\let\csname SETtxideftypefnnl\endcsname
= \relax
\else
\errhelp = \EMsimple
\errmessage{Unknown @txideftypefnnl value `\temp',
must be on|off}%
\fi\fi
}
% Untyped functions:
% @deffn category name args
\makedefun{deffn}#1 #2 #3\endheader{%
\doind{fn}{\code{#2}}%
\printdefname{#1}{}{#2}\magicamp\defunargs{#3\unskip}%
}
% @defop category class name args
\makedefun{defop}#1 {\defopheaderx{#1\ \putwordon}}
\def\defopheaderx#1#2 #3 #4\endheader{%
\doind{fn}{\code{#3}\space\putwordon\ \code{#2}}%
\printdefname{#1\ \code{#2}}{}{#3}\magicamp\defunargs{#4\unskip}%
}
% Typed functions:
% @deftypefn category type name args
\makedefun{deftypefn}#1 #2 #3 #4\endheader{%
\doind{fn}{\code{#3}}%
\doingtypefntrue
\printdefname{#1}{#2}{#3}\defunargs{#4\unskip}%
}
% @deftypeop category class type name args
\makedefun{deftypeop}#1 {\deftypeopheaderx{#1\ \putwordon}}
\def\deftypeopheaderx#1#2 #3 #4 #5\endheader{%
\doind{fn}{\code{#4}\space\putwordon\ \code{#1\ \code{#2}}}%
\doingtypefntrue
\printdefname{#1\ \code{#2}}{#3}{#4}\defunargs{#5\unskip}%
}
% Typed variables:
% @deftypevr category type var args
\makedefun{deftypevr}#1 #2 #3 #4\endheader{%
\doind{vr}{\code{#3}}%
\printdefname{#1}{#2}{#3}\defunargs{#4\unskip}%
}
% @deftypecv category class type var args
\makedefun{deftypecv}#1 {\deftypecvheaderx{#1\ \putwordof}}
\def\deftypecvheaderx#1#2 #3 #4 #5\endheader{%
\doind{vr}{\code{#4}\space\putwordof\ \code{#2}}%
\printdefname{#1\ \code{#2}}{#3}{#4}\defunargs{#5\unskip}%
}
% Untyped variables:
% @defvr category var args
\makedefun{defvr}#1 {\deftypevrheader{#1} {} }
% @defcv category class var args
\makedefun{defcv}#1 {\defcvheaderx{#1\ \putwordof}}
\def\defcvheaderx#1#2 {\deftypecvheaderx{#1}#2 {} }
% Types:
% @deftp category name args
\makedefun{deftp}#1 #2 #3\endheader{%
\doind{tp}{\code{#2}}%
\printdefname{#1}{}{#2}\defunargs{#3\unskip}%
}
% Remaining @defun-like shortcuts:
\makedefun{defun}{\deffnheader{\putwordDeffunc} }
\makedefun{defmac}{\deffnheader{\putwordDefmac} }
\makedefun{defspec}{\deffnheader{\putwordDefspec} }
\makedefun{deftypefun}{\deftypefnheader{\putwordDeffunc} }
\makedefun{defvar}{\defvrheader{\putwordDefvar} }
\makedefun{defopt}{\defvrheader{\putwordDefopt} }
\makedefun{deftypevar}{\deftypevrheader{\putwordDefvar} }
\makedefun{defmethod}{\defopheaderx\putwordMethodon}
\makedefun{deftypemethod}{\deftypeopheaderx\putwordMethodon}
\makedefun{defivar}{\defcvheaderx\putwordInstanceVariableof}
\makedefun{deftypeivar}{\deftypecvheaderx\putwordInstanceVariableof}
% \printdefname, which formats the name of the @def (not the args).
% #1 is the category, such as "Function".
% #2 is the return type, if any.
% #3 is the function name.
%
% We are followed by (but not passed) the arguments, if any.
%
\def\printdefname#1#2#3{%
\par
% Get the values of \leftskip and \rightskip as they were outside the @def...
\advance\leftskip by -\defbodyindent
%
% Determine if we are typesetting the return type of a typed function
% on a line by itself.
\rettypeownlinefalse
\ifdoingtypefn % doing a typed function specifically?
% then check user option for putting return type on its own line:
\ifflagclear{txideftypefnnl}{}{\rettypeownlinetrue}%
\fi
%
% How we'll format the category name. Putting it in brackets helps
% distinguish it from the body text that may end up on the next line
% just below it.
\def\temp{#1}%
\setbox0=\hbox{\kern\deflastargmargin \ifx\temp\empty\else [\rm\temp]\fi}
%
% Figure out line sizes for the paragraph shape. We'll always have at
% least two.
\tempnum = 2
%
% The first line needs space for \box0; but if \rightskip is nonzero,
% we need only space for the part of \box0 which exceeds it:
\dimen0=\hsize \advance\dimen0 by -\wd0 \advance\dimen0 by \rightskip
%
% If doing a return type on its own line, we'll have another line.
\ifrettypeownline
\advance\tempnum by 1
\def\maybeshapeline{0in \hsize}%
\else
\def\maybeshapeline{}%
\fi
%
% The continuations:
\dimen2=\hsize \advance\dimen2 by -\defargsindent
%
% The final paragraph shape:
\parshape \tempnum 0in \dimen0 \maybeshapeline \defargsindent \dimen2
%
% Put the category name at the right margin.
\noindent
\hbox to 0pt{%
\hfil\box0 \kern-\hsize
% \hsize has to be shortened this way:
\kern\leftskip
% Intentionally do not respect \rightskip, since we need the space.
}%
%
% Allow all lines to be underfull without complaint:
\tolerance=10000 \hbadness=10000
\exdentamount=\defbodyindent
{%
\def\^^M{}% for line continuation
%
% defun fonts. We use typewriter by default (used to be bold) because:
% . we're printing identifiers, they should be in tt in principle.
% . in languages with many accents, such as Czech or French, it's
% common to leave accents off identifiers. The result looks ok in
% tt, but exceedingly strange in rm.
% . we don't want -- and --- to be treated as ligatures.
% . this still does not fix the ?` and !` ligatures, but so far no
% one has made identifiers using them :).
\df \tt
\def\temp{#2}% text of the return type
\ifx\temp\empty\else
\tclose{\temp}% typeset the return type
\ifrettypeownline
% put return type on its own line; prohibit line break following:
\hfil\vadjust{\nobreak}\break
\else
\space % type on same line, so just followed by a space
\fi
\fi % no return type
#3% output function name
}%
\ifflagclear{txidefnamenospace}{%
{\rm\enskip}% hskip 0.5 em of \rmfont
}{}%
%
\boldbrax
% arguments will be output next, if any.
}
% Print arguments. Use slanted for @def*, typewriter for @deftype*.
\def\defunargs#1{%
\bgroup
\def\^^M{}% for line continuation
\df \ifdoingtypefn \tt \else \sl \fi
\ifflagclear{txicodevaristt}{}%
{\def\var##1{{\setregularquotes \ttsl ##1}}}%
#1%
\egroup
}
% We want ()&[] to print specially on the defun line.
%
\def\activeparens{%
\catcode`\(=\active \catcode`\)=\active
\catcode`\[=\active \catcode`\]=\active
\catcode`\&=\active
}
% Make control sequences which act like normal parenthesis chars.
\let\lparen = ( \let\rparen = )
% Be sure that we always have a definition for `(', etc. For example,
% if the fn name has parens in it, \boldbrax will not be in effect yet,
% so TeX would otherwise complain about undefined control sequence.
{
\activeparens
\gdef\defcharsdefault{%
\let(=\lparen \let)=\rparen
\let[=\lbrack \let]=\rbrack
\let& = \&%
}
\globaldefs=1 \defcharsdefault
\gdef\boldbrax{\let(=\opnr\let)=\clnr\let[=\lbrb\let]=\rbrb}
\gdef\magicamp{\let&=\amprm}
}
\let\ampchar\&
\newcount\parencount
% If we encounter &foo, then turn on ()-hacking afterwards
\newif\ifampseen
\def\amprm#1 {\ampseentrue{\rm\ }}
\def\parenfont{%
\ifampseen
% At the first level, print parens in roman,
% otherwise use the default font.
\ifnum \parencount=1 \rm \fi
\else
% The \sf parens (in \boldbrax) actually are a little bolder than
% the contained text. This is especially needed for [ and ] .
\sf
\fi
}
\def\infirstlevel#1{%
\ifampseen
\ifnum\parencount=1
#1%
\fi
\fi
}
\def\bfafterword#1 {#1 \bf}
\def\opnr{%
\global\advance\parencount by 1
{\parenfont(}%
\infirstlevel \bfafterword
}
\def\clnr{%
{\parenfont)}%
\infirstlevel \sl
\global\advance\parencount by -1
}
\newcount\brackcount
\def\lbrb{%
\global\advance\brackcount by 1
{\bf[}%
}
\def\rbrb{%
{\bf]}%
\global\advance\brackcount by -1
}
\def\checkparencounts{%
\ifnum\parencount=0 \else \badparencount \fi
\ifnum\brackcount=0 \else \badbrackcount \fi
}
% these should not use \errmessage; the glibc manual, at least, actually
% has such constructs (when documenting function pointers).
\def\badparencount{%
\message{Warning: unbalanced parentheses in @def...}%
\global\parencount=0
}
\def\badbrackcount{%
\message{Warning: unbalanced square brackets in @def...}%
\global\brackcount=0
}
\message{macros,}
% @macro.
% To do this right we need a feature of e-TeX, \scantokens,
% which we arrange to emulate with a temporary file in ordinary TeX.
\ifx\eTeXversion\thisisundefined
\newwrite\macscribble
\def\scantokens#1{%
\toks0={#1}%
\immediate\openout\macscribble=\jobname.tmp
\immediate\write\macscribble{\the\toks0}%
\immediate\closeout\macscribble
\input \jobname.tmp
}
\fi
\let\E=\expandafter
% Used at the time of macro expansion.
% Argument is macro body with arguments substituted
\def\scanmacro#1{%
\newlinechar`\^^M
% expand the expansion of \eatleadingcr twice to maybe remove a leading
% newline (and \else and \fi tokens), then call \eatspaces on the result.
\def\xeatspaces##1{%
\E\E\E\E\E\E\E\eatspaces\E\E\E\E\E\E\E{\eatleadingcr##1%
}}%
\def\xempty##1{}%
%
% Process the macro body under the current catcode regime.
\scantokens{#1@comment}%
%
% The \comment is to remove the \newlinechar added by \scantokens, and
% can be noticed by \parsearg. Note \c isn't used because this means cedilla
% in math mode.
}
% Used for copying and captions
\def\scanexp#1{%
\expandafter\scanmacro\expandafter{#1}%
}
\newcount\paramno % Count of parameters
\newtoks\macname % Macro name
\newif\ifrecursive % Is it recursive?
% List of all defined macros in the form
% \commondummyword\macro1\commondummyword\macro2...
% Currently is also contains all @aliases; the list can be split
% if there is a need.
\def\macrolist{}
% Add the macro to \macrolist
\def\addtomacrolist#1{\expandafter \addtomacrolistxxx \csname#1\endcsname}
\def\addtomacrolistxxx#1{%
\toks0 = \expandafter{\macrolist\commondummyword#1}%
\xdef\macrolist{\the\toks0}%
}
% Utility routines.
% This does \let #1 = #2, with \csnames; that is,
% \let \csname#1\endcsname = \csname#2\endcsname
% (except of course we have to play expansion games).
%
\def\cslet#1#2{%
\expandafter\let
\csname#1\expandafter\endcsname
\csname#2\endcsname
}
% Trim leading and trailing spaces off a string.
% Concepts from aro-bend problem 15 (see CTAN).
{\catcode`\@=11
\gdef\eatspaces #1{\expandafter\trim@\expandafter{#1 }}
\gdef\trim@ #1{\trim@@ @#1 @ #1 @ @@}
\gdef\trim@@ #1@ #2@ #3@@{\trim@@@\empty #2 @}
\def\unbrace#1{#1}
\unbrace{\gdef\trim@@@ #1 } #2@{#1}
}
{\catcode`\^^M=\other%
\gdef\eatleadingcr#1{\if\noexpand#1\noexpand^^M\else\E#1\fi}}%
% Warning: this won't work for a delimited argument
% or for an empty argument
% Trim a single trailing ^^M off a string.
{\catcode`\^^M=\other \catcode`\Q=3%
\gdef\eatcr #1{\eatcra #1Q^^MQ}%
\gdef\eatcra#1^^MQ{\eatcrb#1Q}%
\gdef\eatcrb#1Q#2Q{#1}%
}
% Macro bodies are absorbed as an argument in a context where
% all characters are catcode 10, 11 or 12, except \ which is active
% (as in normal texinfo). It is necessary to change the definition of \
% to recognize macro arguments; this is the job of \mbodybackslash.
%
% Non-ASCII encodings make 8-bit characters active, so un-activate
% them to avoid their expansion. Must do this non-globally, to
% confine the change to the current group.
%
% It's necessary to have hard CRs when the macro is executed. This is
% done by making ^^M (\endlinechar) catcode 12 when reading the macro
% body, and then making it the \newlinechar in \scanmacro.
%
\def\scanctxt{% used as subroutine
\catcode`\"=\other
\catcode`\+=\other
\catcode`\<=\other
\catcode`\>=\other
\catcode`\^=\other
\catcode`\_=\other
\catcode`\|=\other
\catcode`\~=\other
\catcode`\@=\other
\catcode`\^^M=\other
\catcode`\\=\active
\passthroughcharstrue
}
\def\macrobodyctxt{% used for @macro definitions and @copying
\scanctxt
\catcode`\ =\other
\catcode`\{=\other
\catcode`\}=\other
}
% Used when scanning braced macro arguments. Note, however, that catcode
% changes here are ineffectual if the macro invocation was nested inside
% an argument to another Texinfo command.
\def\macroargctxt{%
\scanctxt
\catcode`\ =\active
}
\def\macrolineargctxt{% used for whole-line arguments without braces
\scanctxt
\catcode`\{=\other
\catcode`\}=\other
}
% \mbodybackslash is the definition of \ in @macro bodies.
% It maps \foo\ => \csname macarg.foo\endcsname => #N
% where N is the macro parameter number.
% We define \csname macarg.\endcsname to be \realbackslash, so
% \\ in macro replacement text gets you a backslash.
%
{\catcode`@=0 @catcode`@\=@active
@gdef@usembodybackslash{@let\=@mbodybackslash}
@gdef@mbodybackslash#1\{@csname macarg.#1@endcsname}
}
\expandafter\def\csname macarg.\endcsname{\realbackslash}
\def\margbackslash#1{\char`\#1 }
\def\macro{\recursivefalse\parsearg\macroxxx}
\def\rmacro{\recursivetrue\parsearg\macroxxx}
\def\macroxxx#1{%
\getargs{#1}% now \macname is the macname and \argl the arglist
\ifx\argl\empty % no arguments
\paramno=0\relax
\else
\expandafter\parsemargdef \argl;%
\if\paramno>256\relax
\ifx\eTeXversion\thisisundefined
\errhelp = \EMsimple
\errmessage{You need eTeX to compile a file with macros with more than 256 arguments}
\fi
\fi
\fi
\if1\csname ismacro.\the\macname\endcsname
\message{Warning: redefining \the\macname}%
\else
\expandafter\ifx\csname \the\macname\endcsname \relax
\else \errmessage{Macro name \the\macname\space already defined}\fi
\global\cslet{macsave.\the\macname}{\the\macname}%
\global\expandafter\let\csname ismacro.\the\macname\endcsname=1%
\addtomacrolist{\the\macname}%
\fi
\begingroup \macrobodyctxt \usembodybackslash
\ifrecursive \expandafter\parsermacbody
\else \expandafter\parsemacbody
\fi}
\parseargdef\unmacro{%
\if1\csname ismacro.#1\endcsname
\global\cslet{#1}{macsave.#1}%
\global\expandafter\let \csname ismacro.#1\endcsname=0%
% Remove the macro name from \macrolist:
\begingroup
\expandafter\let\csname#1\endcsname \relax
\let\commondummyword\unmacrodo
\xdef\macrolist{\macrolist}%
\endgroup
\fi
}
% Called by \do from \dounmacro on each macro. The idea is to omit any
% macro definitions that have been changed to \relax.
%
\def\unmacrodo#1{%
\ifx #1\relax
% remove this
\else
\noexpand\commondummyword \noexpand#1%
\fi
}
% \getargs -- Parse the arguments to a @macro line. Set \macname to
% the name of the macro, and \argl to the braced argument list.
\def\getargs#1{\getargsxxx#1{}}
\def\getargsxxx#1#{\getmacname #1 \relax\getmacargs}
\def\getmacname#1 #2\relax{\macname={#1}}
\def\getmacargs#1{\def\argl{#1}}
% This made use of the feature that if the last token of a
% is #, then the preceding argument is delimited by
% an opening brace, and that opening brace is not consumed.
% Parse the optional {params} list to @macro or @rmacro.
% Set \paramno to the number of arguments,
% and \paramlist to a parameter text for the macro (e.g. #1,#2,#3 for a
% three-param macro.) Define \macarg.BLAH for each BLAH in the params
% list to some hook where the argument is to be expanded. If there are
% less than 10 arguments that hook is to be replaced by ##N where N
% is the position in that list, that is to say the macro arguments are to be
% defined `a la TeX in the macro body.
%
% That gets used by \mbodybackslash (above).
%
% If there are 10 or more arguments, a different technique is used: see
% \parsemmanyargdef.
%
\def\parsemargdef#1;{%
\paramno=0\def\paramlist{}%
\let\hash\relax
% \hash is redefined to `#' later to get it into definitions
\let\xeatspaces\relax
\let\xempty\relax
\parsemargdefxxx#1,;,%
\ifnum\paramno<10\relax\else
\paramno0\relax
\parsemmanyargdef@@#1,;,% 10 or more arguments
\fi
}
\def\parsemargdefxxx#1,{%
\if#1;\let\next=\relax
\else \let\next=\parsemargdefxxx
\advance\paramno by 1
\expandafter\edef\csname macarg.\eatspaces{#1}\endcsname
{\xeatspaces{\hash\the\paramno\noexpand\xempty{}}}%
\edef\paramlist{\paramlist\hash\the\paramno,}%
\fi\next}
% the \xempty{} is to give \eatleadingcr an argument in the case of an
% empty macro argument.
% \parsemacbody, \parsermacbody
%
% Read recursive and nonrecursive macro bodies. (They're different since
% rec and nonrec macros end differently.)
%
% We are in \macrobodyctxt, and the \xdef causes backslashes in the macro
% body to be transformed.
% Set \macrobody to the body of the macro, and call \macrodef.
%
{\catcode`\ =\other\long\gdef\parsemacbody#1@end macro{%
\xdef\macrobody{\eatcr{#1}}\endgroup\macrodef}}%
{\catcode`\ =\other\long\gdef\parsermacbody#1@end rmacro{%
\xdef\macrobody{\eatcr{#1}}\endgroup\macrodef}}%
% Make @ a letter, so that we can make private-to-Texinfo macro names.
\edef\texiatcatcode{\the\catcode`\@}
\catcode `@=11\relax
%%%%%%%%%%%%%% Code for > 10 arguments only %%%%%%%%%%%%%%%%%%
% If there are 10 or more arguments, a different technique is used, where the
% hook remains in the body, and when macro is to be expanded the body is
% processed again to replace the arguments.
%
% In that case, the hook is \the\toks N-1, and we simply set \toks N-1 to the
% argument N value and then \edef the body (nothing else will expand because of
% the catcode regime under which the body was input).
%
% If you compile with TeX (not eTeX), and you have macros with 10 or more
% arguments, no macro can have more than 256 arguments (else error).
%
% In case that there are 10 or more arguments we parse again the arguments
% list to set new definitions for the \macarg.BLAH macros corresponding to
% each BLAH argument. It was anyhow needed to parse already once this list
% in order to count the arguments, and as macros with at most 9 arguments
% are by far more frequent than macro with 10 or more arguments, defining
% twice the \macarg.BLAH macros does not cost too much processing power.
\def\parsemmanyargdef@@#1,{%
\if#1;\let\next=\relax
\else
\let\next=\parsemmanyargdef@@
\edef\tempb{\eatspaces{#1}}%
\expandafter\def\expandafter\tempa
\expandafter{\csname macarg.\tempb\endcsname}%
% Note that we need some extra \noexpand\noexpand, this is because we
% don't want \the to be expanded in the \parsermacbody as it uses an
% \xdef .
\expandafter\edef\tempa
{\noexpand\noexpand\noexpand\the\toks\the\paramno}%
\advance\paramno by 1\relax
\fi\next}
\let\endargs@\relax
\let\nil@\relax
\def\nilm@{\nil@}%
\long\def\nillm@{\nil@}%
% This macro is expanded during the Texinfo macro expansion, not during its
% definition. It gets all the arguments' values and assigns them to macros
% macarg.ARGNAME
%
% #1 is the macro name
% #2 is the list of argument names
% #3 is the list of argument values
\def\getargvals@#1#2#3{%
\def\macargdeflist@{}%
\def\saveparamlist@{#2}% Need to keep a copy for parameter expansion.
\def\paramlist{#2,\nil@}%
\def\macroname{#1}%
\begingroup
\macroargctxt
\def\argvaluelist{#3,\nil@}%
\def\@tempa{#3}%
\ifx\@tempa\empty
\setemptyargvalues@
\else
\getargvals@@
\fi
}
\def\getargvals@@{%
\ifx\paramlist\nilm@
% Some sanity check needed here that \argvaluelist is also empty.
\ifx\argvaluelist\nillm@
\else
\errhelp = \EMsimple
\errmessage{Too many arguments in macro `\macroname'!}%
\fi
\let\next\macargexpandinbody@
\else
\ifx\argvaluelist\nillm@
% No more arguments values passed to macro. Set remaining named-arg
% macros to empty.
\let\next\setemptyargvalues@
\else
% pop current arg name into \@tempb
\def\@tempa##1{\pop@{\@tempb}{\paramlist}##1\endargs@}%
\expandafter\@tempa\expandafter{\paramlist}%
% pop current argument value into \@tempc
\def\@tempa##1{\longpop@{\@tempc}{\argvaluelist}##1\endargs@}%
\expandafter\@tempa\expandafter{\argvaluelist}%
% Here \@tempb is the current arg name and \@tempc is the current arg value.
% First place the new argument macro definition into \@tempd
\expandafter\macname\expandafter{\@tempc}%
\expandafter\let\csname macarg.\@tempb\endcsname\relax
\expandafter\def\expandafter\@tempe\expandafter{%
\csname macarg.\@tempb\endcsname}%
\edef\@tempd{\long\def\@tempe{\the\macname}}%
\push@\@tempd\macargdeflist@
\let\next\getargvals@@
\fi
\fi
\next
}
\def\push@#1#2{%
\expandafter\expandafter\expandafter\def
\expandafter\expandafter\expandafter#2%
\expandafter\expandafter\expandafter{%
\expandafter#1#2}%
}
% Replace arguments by their values in the macro body, and place the result
% in macro \@tempa.
%
\def\macvalstoargs@{%
% To do this we use the property that token registers that are \the'ed
% within an \edef expand only once. So we are going to place all argument
% values into respective token registers.
%
% First we save the token context, and initialize argument numbering.
\begingroup
\paramno0\relax
% Then, for each argument number #N, we place the corresponding argument
% value into a new token list register \toks#N
\expandafter\putargsintokens@\saveparamlist@,;,%
% Then, we expand the body so that argument are replaced by their
% values. The trick for values not to be expanded themselves is that they
% are within tokens and that tokens expand only once in an \edef .
\edef\@tempc{\csname mac.\macroname .body\endcsname}%
% Now we restore the token stack pointer to free the token list registers
% which we have used, but we make sure that expanded body is saved after
% group.
\expandafter
\endgroup
\expandafter\def\expandafter\@tempa\expandafter{\@tempc}%
}
% Define the named-macro outside of this group and then close this group.
%
\def\macargexpandinbody@{%
\expandafter
\endgroup
\macargdeflist@
% First the replace in body the macro arguments by their values, the result
% is in \@tempa .
\macvalstoargs@
% Then we point at the \norecurse or \gobble (for recursive) macro value
% with \@tempb .
\expandafter\let\expandafter\@tempb\csname mac.\macroname .recurse\endcsname
% Depending on whether it is recursive or not, we need some tailing
% \egroup .
\ifx\@tempb\gobble
\let\@tempc\relax
\else
\let\@tempc\egroup
\fi
% And now we do the real job:
\edef\@tempd{\noexpand\@tempb{\macroname}\noexpand\scanmacro{\@tempa}\@tempc}%
\@tempd
}
\def\putargsintokens@#1,{%
\if#1;\let\next\relax
\else
\let\next\putargsintokens@
% First we allocate the new token list register, and give it a temporary
% alias \@tempb .
\toksdef\@tempb\the\paramno
% Then we place the argument value into that token list register.
\expandafter\let\expandafter\@tempa\csname macarg.#1\endcsname
\expandafter\@tempb\expandafter{\@tempa}%
\advance\paramno by 1\relax
\fi
\next
}
% Trailing missing arguments are set to empty.
%
\def\setemptyargvalues@{%
\ifx\paramlist\nilm@
\let\next\macargexpandinbody@
\else
\expandafter\setemptyargvaluesparser@\paramlist\endargs@
\let\next\setemptyargvalues@
\fi
\next
}
\def\setemptyargvaluesparser@#1,#2\endargs@{%
\expandafter\def\expandafter\@tempa\expandafter{%
\expandafter\def\csname macarg.#1\endcsname{}}%
\push@\@tempa\macargdeflist@
\def\paramlist{#2}%
}
% #1 is the element target macro
% #2 is the list macro
% #3,#4\endargs@ is the list value
\def\pop@#1#2#3,#4\endargs@{%
\def#1{#3}%
\def#2{#4}%
}
\long\def\longpop@#1#2#3,#4\endargs@{%
\long\def#1{#3}%
\long\def#2{#4}%
}
%%%%%%%%%%%%%% End of code for > 10 arguments %%%%%%%%%%%%%%%%%%
% This defines a Texinfo @macro or @rmacro, called by \parsemacbody.
% \macrobody has the body of the macro in it, with placeholders for
% its parameters, looking like "\xeatspaces{\hash 1}".
% \paramno is the number of parameters
% \paramlist is a TeX parameter text, e.g. "#1,#2,#3,"
% There are four cases: macros of zero, one, up to nine, and many arguments.
% \xdef is used so that macro definitions will survive the file
% they're defined in: @include reads the file inside a group.
%
\def\macrodef{%
\let\hash=##% convert placeholders to macro parameter chars
\ifnum\paramno=1
\long\def\xeatspaces##1{##1}%
% We don't use \xeatspaces for single-argument macros, because we
% want to keep ends of lines. This definition removes \xeatspaces
% when \macrobody is expanded below.
\else
\def\xeatspaces{\string\xeatspaces}%
% This expands \xeatspaces as a sequence of character tokens, which
% stops \scantokens inserting an extra space after the control sequence.
\fi
\ifcase\paramno
% 0
\expandafter\xdef\csname\the\macname\endcsname{%
\begingroup
\noexpand\spaceisspace
\noexpand\endlineisspace
\noexpand\expandafter % skip any whitespace after the macro name.
\expandafter\noexpand\csname\the\macname @@@\endcsname}%
\expandafter\xdef\csname\the\macname @@@\endcsname{%
\endgroup
\noexpand\scanmacro{\macrobody}}%
\or % 1
\expandafter\xdef\csname\the\macname\endcsname{%
\begingroup
\noexpand\braceorline
\expandafter\noexpand\csname\the\macname @@@\endcsname}%
\expandafter\xdef\csname\the\macname @@@\endcsname##1{%
\endgroup
\noexpand\scanmacro{\macrobody}%
}%
\else % at most 9
\ifnum\paramno<10\relax
% @MACNAME sets the context for reading the macro argument
% @MACNAME@@ gets the argument, processes backslashes and appends a
% comma.
% @MACNAME@@@ removes braces surrounding the argument list.
% @MACNAME@@@@ scans the macro body with arguments substituted.
\expandafter\xdef\csname\the\macname\endcsname{%
\begingroup
\noexpand\expandafter % This \expandafter skip any spaces after the
\noexpand\macroargctxt % macro before we change the catcode of space.
\noexpand\expandafter
\expandafter\noexpand\csname\the\macname @@\endcsname}%
\expandafter\xdef\csname\the\macname @@\endcsname##1{%
\noexpand\passargtomacro
\expandafter\noexpand\csname\the\macname @@@\endcsname{##1,}}%
\expandafter\xdef\csname\the\macname @@@\endcsname##1{%
\expandafter\noexpand\csname\the\macname @@@@\endcsname ##1}%
\expandafter\expandafter
\expandafter\xdef
\expandafter\expandafter
\csname\the\macname @@@@\endcsname\paramlist{%
\endgroup\noexpand\scanmacro{\macrobody}}%
\else % 10 or more:
\expandafter\xdef\csname\the\macname\endcsname{%
\noexpand\getargvals@{\the\macname}{\argl}%
}%
\global\expandafter\let\csname mac.\the\macname .body\endcsname\macrobody
\global\expandafter\let\csname mac.\the\macname .recurse\endcsname\gobble
\fi
\fi}
\catcode `\@\texiatcatcode\relax % end private-to-Texinfo catcodes
\def\norecurse#1{\bgroup\cslet{#1}{macsave.#1}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
{\catcode`\@=0 \catcode`\\=13 % We need to manipulate \ so use @ as escape
@catcode`@_=11 % private names
@catcode`@!=11 % used as argument separator
% \passargtomacro#1#2 -
% Call #1 with a list of tokens #2, with any doubled backslashes in #2
% compressed to one.
%
% This implementation works by expansion, and not execution (so we cannot use
% \def or similar). This reduces the risk of this failing in contexts where
% complete expansion is done with no execution (for example, in writing out to
% an auxiliary file for an index entry).
%
% State is kept in the input stream: the argument passed to
% @look_ahead, @gobble_and_check_finish and @add_segment is
%
% THE_MACRO ARG_RESULT ! {PENDING_BS} NEXT_TOKEN (... rest of input)
%
% where:
% THE_MACRO - name of the macro we want to call
% ARG_RESULT - argument list we build to pass to that macro
% PENDING_BS - either a backslash or nothing
% NEXT_TOKEN - used to look ahead in the input stream to see what's coming next
@gdef@passargtomacro#1#2{%
@add_segment #1!{}@relax#2\@_finish\%
}
@gdef@_finish{@_finishx} @global@let@_finishx@relax
% #1 - THE_MACRO ARG_RESULT
% #2 - PENDING_BS
% #3 - NEXT_TOKEN
% #4 used to look ahead
%
% If the next token is not a backslash, process the rest of the argument;
% otherwise, remove the next token.
@gdef@look_ahead#1!#2#3#4{%
@ifx#4\%
@expandafter@gobble_and_check_finish
@else
@expandafter@add_segment
@fi#1!{#2}#4#4%
}
% #1 - THE_MACRO ARG_RESULT
% #2 - PENDING_BS
% #3 - NEXT_TOKEN
% #4 should be a backslash, which is gobbled.
% #5 looks ahead
%
% Double backslash found. Add a single backslash, and look ahead.
@gdef@gobble_and_check_finish#1!#2#3#4#5{%
@add_segment#1\!{}#5#5%
}
@gdef@is_fi{@fi}
% #1 - THE_MACRO ARG_RESULT
% #2 - PENDING_BS
% #3 - NEXT_TOKEN
% #4 is input stream until next backslash
%
% Input stream is either at the start of the argument, or just after a
% backslash sequence, either a lone backslash, or a doubled backslash.
% NEXT_TOKEN contains the first token in the input stream: if it is \finish,
% finish; otherwise, append to ARG_RESULT the segment of the argument up until
% the next backslash. PENDING_BACKSLASH contains a backslash to represent
% a backslash just before the start of the input stream that has not been
% added to ARG_RESULT.
@gdef@add_segment#1!#2#3#4\{%
@ifx#3@_finish
@call_the_macro#1!%
@else
% append the pending backslash to the result, followed by the next segment
@expandafter@is_fi@look_ahead#1#2#4!{\}@fi
% this @fi is discarded by @look_ahead.
% we can't get rid of it with \expandafter because we don't know how
% long #4 is.
}
% #1 - THE_MACRO
% #2 - ARG_RESULT
% #3 discards the res of the conditional in @add_segment, and @is_fi ends the
% conditional.
@gdef@call_the_macro#1#2!#3@fi{@is_fi #1{#2}}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% \braceorline MAC is used for a one-argument macro MAC. It checks
% whether the next non-whitespace character is a {. It sets the context
% for reading the argument (slightly different in the two cases). Then,
% to read the argument, in the whole-line case, it then calls the regular
% \parsearg MAC; in the lbrace case, it calls \passargtomacro MAC.
%
\def\braceorline#1{\let\macnamexxx=#1\futurelet\nchar\braceorlinexxx}
\def\braceorlinexxx{%
\ifx\nchar\bgroup
\macroargctxt
\expandafter\passargtomacro
\else
\macrolineargctxt\expandafter\parsearg
\fi \macnamexxx}
% @linemacro
\parseargdef\linemacro{%
\getargs{#1}% now \macname is the macname and \argl the arglist
\ifx\argl\empty
\paramno=0
\let\hash\relax
\def\paramlist{\hash 1\endlinemacro}%
\else
\expandafter\linegetparamlist\argl;%
\fi
\begingroup \macrobodyctxt \usembodybackslash
\parselinemacrobody
}
% Build up \paramlist which will be used as the parameter text for the macro.
% At the end it will be like "#1 #2 #3\endlinemacro".
\def\linegetparamlist#1;{%
\paramno=0\def\paramlist{}%
\let\hash\relax
\linegetparamlistxxx#1,;,%
}
\def\linegetparamlistxxx#1,{%
\if#1;\let\next=\linegetparamlistxxxx
\else \let\next=\linegetparamlistxxx
\advance\paramno by 1
\expandafter\edef\csname macarg.\eatspaces{#1}\endcsname
{\hash\the\paramno}%
\edef\paramlist{\paramlist\hash\the\paramno\space}%
\fi\next}
\def\linegetparamlistxxxx{%
\expandafter\fixparamlist\paramlist\fixparamlist
}
% Replace final space token
\def\fixparamlist#1 \fixparamlist{%
\def\paramlist{#1\endlinemacro}%
}
% Read the body of the macro, replacing backslash-surrounded variables
%
{\catcode`\ =\other\long\gdef\parselinemacrobody#1@end linemacro{%
\xdef\macrobody{#1}%
\endgroup
\linemacrodef
}}
% Make the definition
\def\linemacrodef{%
\let\hash=##%
\expandafter\xdef\csname\the\macname\endcsname{%
\bgroup
\noexpand\parsearg
\expandafter\noexpand\csname\the\macname @@\endcsname
}
\expandafter\xdef\csname\the\macname @@\endcsname##1{%
\egroup
\expandafter\noexpand
\csname\the\macname @@@\endcsname##1\noexpand\endlinemacro
}
\expandafter\expandafter
\expandafter\xdef
\expandafter\expandafter\csname\the\macname @@@\endcsname\paramlist{%
\newlinechar=13 % split \macrobody into lines
\noexpand\scantokens{\macrobody}%
}
}
% @alias.
% We need some trickery to remove the optional spaces around the equal
% sign. Make them active and then expand them all to nothing.
%
\def\alias{\parseargusing\obeyspaces\aliasxxx}
\def\aliasxxx #1{\aliasyyy#1\relax}
\def\aliasyyy #1=#2\relax{%
{%
\expandafter\let\obeyedspace=\empty
\addtomacrolist{#1}%
\xdef\next{\global\let\makecsname{#1}=\makecsname{#2}}%
}%
\next
}
\message{cross references,}
\newwrite\auxfile
\newif\ifhavexrefs % True if xref values are known.
\newif\ifwarnedxrefs % True if we warned once that they aren't known.
% @inforef is relatively simple.
\def\inforef #1{\inforefzzz #1,,,,**}
\def\inforefzzz #1,#2,#3,#4**{%
\putwordSee{} \putwordInfo{} \putwordfile{} \file{\ignorespaces #3{}},
node \samp{\ignorespaces#1{}}}
% @node's only job in TeX is to define \lastnode, which is used in
% cross-references. The @node line might or might not have commas, and
% might or might not have spaces before the first comma, like:
% @node foo , bar , ...
% We don't want such trailing spaces in the node name.
%
\parseargdef\node{\checkenv{}\donode #1 ,\finishnodeparse}
%
% also remove a trailing comma, in case of something like this:
% @node Help-Cross, , , Cross-refs
\def\donode#1 ,#2\finishnodeparse{\dodonode #1,\finishnodeparse}
\def\dodonode#1,#2\finishnodeparse{\gdef\lastnode{#1}\omittopnode}
% Used so that the @top node doesn't have to be wrapped in an @ifnottex
% conditional.
% \doignore goes to more effort to skip nested conditionals but we don't need
% that here.
\def\omittopnode{%
\ifx\lastnode\wordTop
\expandafter\ignorenode\fi
}
\def\wordTop{Top}
% Until the next @node, @part or @bye command, divert output to a box that
% is not output.
\def\ignorenode{\setbox\dummybox\vbox\bgroup
\def\part{\egroup\part}%
\def\node{\egroup\node}%
\ignorenodebye
}
{\let\bye\relax
\gdef\ignorenodebye{\let\bye\ignorenodebyedef}
\gdef\ignorenodebyedef{\egroup(`Top' node ignored)\bye}}
% The redefinition of \bye here is because it is declared \outer
\let\lastnode=\empty
% Write a cross-reference definition for the current node. #1 is the
% type (Ynumbered, Yappendix, Ynothing).
%
\def\donoderef#1{%
\ifx\lastnode\empty\else
\setref{\lastnode}{#1}%
\global\let\lastnode=\empty
\fi
}
% @nodedescription, @nodedescriptionblock - do nothing for TeX
\parseargdef\nodedescription{}
\def\nodedescriptionblock{\doignore{nodedescriptionblock}}
% @anchor{NAME} -- define xref target at arbitrary point.
%
\newcount\savesfregister
%
\def\savesf{\relax \ifhmode \savesfregister=\spacefactor \fi}
\def\restoresf{\relax \ifhmode \spacefactor=\savesfregister \fi}
\def\anchor#1{\savesf \setref{#1}{Ynothing}\restoresf \ignorespaces}
% \setref{NAME}{SNT} defines a cross-reference point NAME (a node or an
% anchor), which consists of three parts:
% 1) NAME-title - the current sectioning name taken from \currentsection,
% or the anchor name.
% 2) NAME-snt - section number and type, passed as the SNT arg, or
% empty for anchors.
% 3) NAME-pg - the page number.
%
% This is called from \donoderef, \anchor, and \dofloat. In the case of
% floats, there is an additional part, which is not written here:
% 4) NAME-lof - the text as it should appear in a @listoffloats.
%
\def\setref#1#2{%
\pdfmkdest{#1}%
\iflinks
{%
\requireauxfile
\atdummies % preserve commands, but don't expand them
% match definition in \xrdef, \refx, \xrefX.
\def\value##1{##1}%
\edef\writexrdef##1##2{%
\write\auxfile{@xrdef{#1-% #1 of \setref, expanded by the \edef
##1}{##2}}% these are parameters of \writexrdef
}%
\toks0 = \expandafter{\currentsection}%
\immediate \writexrdef{title}{\the\toks0 }%
\immediate \writexrdef{snt}{\csname #2\endcsname}% \Ynumbered etc.
\safewhatsit{\writexrdef{pg}{\folio}}% will be written later, at \shipout
}%
\fi
}
% @xrefautosectiontitle on|off says whether @section(ing) names are used
% automatically in xrefs, if the third arg is not explicitly specified.
% This was provided as a "secret" @set xref-automatic-section-title
% variable, now it's official.
%
\parseargdef\xrefautomaticsectiontitle{%
\def\temp{#1}%
\ifx\temp\onword
\expandafter\let\csname SETxref-automatic-section-title\endcsname
= \empty
\else\ifx\temp\offword
\expandafter\let\csname SETxref-automatic-section-title\endcsname
= \relax
\else
\errhelp = \EMsimple
\errmessage{Unknown @xrefautomaticsectiontitle value `\temp',
must be on|off}%
\fi\fi
}
%
% @xref, @pxref, and @ref generate cross-references. For \xrefX, #1 is
% the node name, #2 the name of the Info cross-reference, #3 the printed
% node name, #4 the name of the Info file, #5 the name of the printed
% manual. All but the node name can be omitted.
%
\def\pxref{\putwordsee{} \xrefXX}
\def\xref{\putwordSee{} \xrefXX}
\def\ref{\xrefXX}
\def\xrefXX#1{\def\xrefXXarg{#1}\futurelet\tokenafterxref\xrefXXX}
\def\xrefXXX{\expandafter\xrefX\expandafter[\xrefXXarg,,,,,,,]}
%
\newbox\toprefbox
\newbox\printedrefnamebox
\newbox\infofilenamebox
\newbox\printedmanualbox
%
\def\xrefX[#1,#2,#3,#4,#5,#6]{\begingroup
\unsepspaces
%
\getprintedrefname{#1}{#3}{#5}%
\def\infofilename{\ignorespaces #4}%
\setbox\infofilenamebox = \hbox{\infofilename\unskip}%
%
\startxreflink{#1}{#4}%
{%
% Have to otherify everything special to allow the \csname to
% include an _ in the xref name, etc.
\indexnofonts
\turnoffactive
\def\value##1{##1}%
\expandafter\global\expandafter\let\expandafter\Xthisreftitle
\csname XR#1-title\endcsname
}%
%
% Float references are printed completely differently: "Figure 1.2"
% instead of "[somenode], p.3". \iffloat distinguishes them by
% \Xthisreftitle being set to a magic string.
\iffloat\Xthisreftitle
% If the user specified the print name (third arg) to the ref,
% print it instead of our usual "Figure 1.2".
\ifdim\wd\printedrefnamebox = 0pt
\refx{#1-snt}%
\else
\printedrefname
\fi
%
% If the user also gave the printed manual name (fifth arg), append
% "in MANUALNAME".
\ifdim \wd\printedmanualbox > 0pt
\space \putwordin{} \cite{\printedmanual}%
\fi
\else
% node/anchor (non-float) references.
%
% If we use \unhbox to print the node names, TeX does not insert
% empty discretionaries after hyphens, which means that it will not
% find a line break at a hyphen in a node names. Since some manuals
% are best written with fairly long node names, containing hyphens,
% this is a loss. Therefore, we give the text of the node name
% again, so it is as if TeX is seeing it for the first time.
%
\ifdim \wd\printedmanualbox > 0pt
% Cross-manual reference with a printed manual name.
%
\crossmanualxref{\cite{\printedmanual\unskip}}%
%
\else\ifdim \wd\infofilenamebox > 0pt
% Cross-manual reference with only an info filename (arg 4), no
% printed manual name (arg 5). This is essentially the same as
% the case above; we output the filename, since we have nothing else.
%
\crossmanualxref{\code{\infofilename\unskip}}%
%
\else
% Reference within this manual.
%
% Only output a following space if the -snt ref is nonempty, as the ref
% will be empty for @unnumbered and @anchor.
\setbox2 = \hbox{\ignorespaces \refx{#1-snt}}%
\ifdim \wd2 > 0pt \refx{#1-snt}\space\fi
%
% output the `[mynode]' via the macro below so it can be overridden.
\xrefprintnodename\printedrefname
%
\ifflagclear{txiomitxrefpg}{%
% We always want a comma
,%
% output the `page 3'.
\turnoffactive \putpageref{#1}%
% Add a , if xref followed by a space
\if\space\noexpand\tokenafterxref ,%
\else\ifx\ \tokenafterxref ,% @TAB
\else\ifx\*\tokenafterxref ,% @*
\else\ifx\ \tokenafterxref ,% @SPACE
\else\ifx\
\tokenafterxref ,% @NL
\else\ifx\tie\tokenafterxref ,% @tie
\fi\fi\fi\fi\fi\fi
}{}%
\fi\fi
\fi
\endlink
\endgroup}
% \getprintedrefname{NODE}{LABEL}{MANUAL}
% - set \printedrefname and \printedmanual
%
\def\getprintedrefname#1#2#3{%
% Get args without leading/trailing spaces.
\def\printedrefname{\ignorespaces #2}%
\setbox\printedrefnamebox = \hbox{\printedrefname\unskip}%
%
\def\printedmanual{\ignorespaces #3}%
\setbox\printedmanualbox = \hbox{\printedmanual\unskip}%
%
% If the printed reference name (arg #2) was not explicitly given in
% the @xref, figure out what we want to use.
\ifdim \wd\printedrefnamebox = 0pt
% No printed node name was explicitly given.
\expandafter\ifx\csname SETxref-automatic-section-title\endcsname \relax
% Not auto section-title: use node name inside the square brackets.
\def\printedrefname{\ignorespaces #1}%
\else
% Auto section-title: use chapter/section title inside
% the square brackets if we have it.
\ifdim \wd\printedmanualbox > 0pt
% It is in another manual, so we don't have it; use node name.
\def\printedrefname{\ignorespaces #1}%
\else
\ifhavexrefs
% We (should) know the real title if we have the xref values.
\def\printedrefname{\refx{#1-title}}%
\else
% Otherwise just copy the Info node name.
\def\printedrefname{\ignorespaces #1}%
\fi%
\fi
\fi
\fi
}
% \startxreflink{NODE}{FILE} - start link in pdf output.
\def\startxreflink#1#2{%
\ifpdforxetex
% For pdfTeX and LuaTeX
{\indexnofonts
\makevalueexpandable
\turnoffactive
% This expands tokens, so do it after making catcode changes, so _
% etc. don't get their TeX definitions. This ignores all spaces in
% #2, including (wrongly) those in the middle of the filename.
\getfilename{#2}%
%
% This (wrongly) does not take account of leading or trailing
% spaces in #1, which should be ignored.
\setpdfdestname{#1}%
%
\ifx\pdfdestname\empty
\def\pdfdestname{Top}% no empty targets
\fi
%
\leavevmode
\ifpdf
\startlink attr{/Border [0 0 0]}%
\ifnum\filenamelength>0
goto file{\the\filename.pdf} name{\pdfdestname}%
\else
goto name{\pdfmkpgn{\pdfdestname}}%
\fi
\else % XeTeX
\ifnum\filenamelength>0
% With default settings,
% XeTeX (xdvipdfmx) replaces link destination names with integers.
% In this case, the replaced destination names of
% remote PDFs are no longer known. In order to avoid a replacement,
% you can use xdvipdfmx's command line option `-C 0x0010'.
% If you use XeTeX 0.99996+ (TeX Live 2016+),
% this command line option is no longer necessary
% because we can use the `dvipdfmx:config' special.
\special{pdf:bann << /Border [0 0 0] /Type /Annot /Subtype /Link /A
<< /S /GoToR /F (\the\filename.pdf) /D (\pdfdestname) >> >>}%
\else
\special{pdf:bann << /Border [0 0 0] /Type /Annot /Subtype /Link /A
<< /S /GoTo /D (\pdfdestname) >> >>}%
\fi
\fi
}%
\setcolor{\linkcolor}%
\fi
}
% can be overridden in translation files
\def\putpageref#1{%
\space\putwordpage\tie\refx{#1-pg}}
% Output a cross-manual xref to #1. Used just above (twice).
%
% Only include the text "Section ``foo'' in" if the foo is neither
% missing or Top. Thus, @xref{,,,foo,The Foo Manual} outputs simply
% "see The Foo Manual", the idea being to refer to the whole manual.
%
% But, this being TeX, we can't easily compare our node name against the
% string "Top" while ignoring the possible spaces before and after in
% the input. By adding the arbitrary 7sp below, we make it much less
% likely that a real node name would have the same width as "Top" (e.g.,
% in a monospaced font). Hopefully it will never happen in practice.
%
% For the same basic reason, we retypeset the "Top" at every
% reference, since the current font is indeterminate.
%
\def\crossmanualxref#1{%
\setbox\toprefbox = \hbox{Top\kern7sp}%
\setbox2 = \hbox{\ignorespaces \printedrefname \unskip \kern7sp}%
\ifdim \wd2 > 7sp % nonempty?
\ifdim \wd2 = \wd\toprefbox \else % same as Top?
\putwordSection{} ``\printedrefname'' \putwordin{}\space
\fi
\fi
#1%
}
% This macro is called from \xrefX for the `[nodename]' part of xref
% output. It's a separate macro only so it can be changed more easily,
% since square brackets don't work well in some documents. Particularly
% one that Bob is working on :).
%
\def\xrefprintnodename#1{[#1]}
% @link{NODENAME, LABEL, MANUAL} - create a "plain" link, with no
% page number. Not useful if printed on paper.
%
\def\link#1{\linkX[#1,,,]}
\def\linkX[#1,#2,#3,#4]{%
\begingroup
\unsepspaces
\getprintedrefname{#1}{#2}{#3}%
\startxreflink{#1}{#3}%
\printedrefname
\endlink
\endgroup
}
% Things referred to by \setref.
%
\def\Ynothing{}
\def\Yomitfromtoc{}
\def\Ynumbered{%
\ifnum\secno=0
\putwordChapter@tie \the\chapno
\else \ifnum\subsecno=0
\putwordSection@tie \the\chapno.\the\secno
\else \ifnum\subsubsecno=0
\putwordSection@tie \the\chapno.\the\secno.\the\subsecno
\else
\putwordSection@tie \the\chapno.\the\secno.\the\subsecno.\the\subsubsecno
\fi\fi\fi
}
\def\Yappendix{%
\ifnum\secno=0
\putwordAppendix@tie @char\the\appendixno{}%
\else \ifnum\subsecno=0
\putwordSection@tie @char\the\appendixno.\the\secno
\else \ifnum\subsubsecno=0
\putwordSection@tie @char\the\appendixno.\the\secno.\the\subsecno
\else
\putwordSection@tie
@char\the\appendixno.\the\secno.\the\subsecno.\the\subsubsecno
\fi\fi\fi
}
% \refx{NAME} - reference a cross-reference string named NAME.
\def\refx#1{%
\requireauxfile
{%
\indexnofonts
\turnoffactive
\def\value##1{##1}%
\expandafter\global\expandafter\let\expandafter\thisrefX
\csname XR#1\endcsname
}%
\ifx\thisrefX\relax
% If not defined, say something at least.
\angleleft un\-de\-fined\angleright
\iflinks
\ifhavexrefs
{\toks0 = {#1}% avoid expansion of possibly-complex value
\message{\linenumber Undefined cross reference `\the\toks0'.}}%
\else
\ifwarnedxrefs\else
\global\warnedxrefstrue
\message{Cross reference values unknown; you must run TeX again.}%
\fi
\fi
\fi
\else
% It's defined, so just use it.
\thisrefX
\fi
}
% This is the macro invoked by entries in the aux file. Define a control
% sequence for a cross-reference target (we prepend XR to the control sequence
% name to avoid collisions). The value is the page number. If this is a float
% type, we have more work to do.
%
\def\xrdef#1#2{%
{% Expand the node or anchor name to remove control sequences.
% \turnoffactive stops 8-bit characters being changed to commands
% like @'e. \refx does the same to retrieve the value in the definition.
\indexnofonts
\turnoffactive
\def\value##1{##1}%
\xdef\safexrefname{#1}%
}%
%
\bgroup
\expandafter\gdef\csname XR\safexrefname\endcsname{#2}%
\egroup
% We put the \gdef inside a group to avoid the definitions building up on
% TeX's save stack, which can cause it to run out of space for aux files with
% thousands of lines. \gdef doesn't use the save stack, but \csname does
% when it defines an unknown control sequence as \relax.
%
% Was that xref control sequence that we just defined for a float?
\expandafter\iffloat\csname XR\safexrefname\endcsname
% it was a float, and we have the (safe) float type in \iffloattype.
\expandafter\let\expandafter\floatlist
\csname floatlist\iffloattype\endcsname
%
% Is this the first time we've seen this float type?
\expandafter\ifx\floatlist\relax
\toks0 = {\do}% yes, so just \do
\else
% had it before, so preserve previous elements in list.
\toks0 = \expandafter{\floatlist\do}%
\fi
%
% Remember this xref in the control sequence \floatlistFLOATTYPE,
% for later use in \listoffloats.
\expandafter\xdef\csname floatlist\iffloattype\endcsname{\the\toks0
{\safexrefname}}%
\fi
}
% If working on a large document in chapters, it is convenient to
% be able to disable indexing, cross-referencing, and contents, for test runs.
% This is done with @novalidate at the beginning of the file.
%
\newif\iflinks \linkstrue % by default we want the aux files.
\let\novalidate = \linksfalse
% Used when writing to the aux file, or when using data from it.
\def\requireauxfile{%
\iflinks
\tryauxfile
% Open the new aux file. TeX will close it automatically at exit.
\immediate\openout\auxfile=\jobname.aux
\fi
\global\let\requireauxfile=\relax % Only do this once.
}
% Read the last existing aux file, if any. No error if none exists.
%
\def\tryauxfile{%
\openin 1 \jobname.aux
\ifeof 1 \else
\readdatafile{aux}%
\global\havexrefstrue
\fi
\closein 1
}
\def\setupdatafile{%
\catcode`\^^@=\other
\catcode`\^^A=\other
\catcode`\^^B=\other
\catcode`\^^C=\other
\catcode`\^^D=\other
\catcode`\^^E=\other
\catcode`\^^F=\other
\catcode`\^^G=\other
\catcode`\^^H=\other
\catcode`\^^K=\other
\catcode`\^^L=\other
\catcode`\^^N=\other
\catcode`\^^P=\other
\catcode`\^^Q=\other
\catcode`\^^R=\other
\catcode`\^^S=\other
\catcode`\^^T=\other
\catcode`\^^U=\other
\catcode`\^^V=\other
\catcode`\^^W=\other
\catcode`\^^X=\other
\catcode`\^^Z=\other
\catcode`\^^[=\other
\catcode`\^^\=\other
\catcode`\^^]=\other
\catcode`\^^^=\other
\catcode`\^^_=\other
\catcode`\^=\other
%
% Special characters. Should be turned off anyway, but...
\catcode`\~=\other
\catcode`\[=\other
\catcode`\]=\other
\catcode`\"=\other
\catcode`\_=\active
\catcode`\|=\active
\catcode`\<=\active
\catcode`\>=\active
\catcode`\$=\other
\catcode`\#=\other
\catcode`\&=\other
\catcode`\%=\other
\catcode`+=\other % avoid \+ for paranoia even though we've turned it off
%
\catcode`\\=\active
%
% @ is our escape character in .aux files, and we need braces.
\catcode`\{=1
\catcode`\}=2
\catcode`\@=0
}
\def\readdatafile#1{%
\begingroup
\setupdatafile
\input\jobname.#1
\endgroup}
\message{insertions,}
% including footnotes.
\newcount \footnoteno
% The trailing space in the following definition for supereject is
% vital for proper filling; pages come out unaligned when you do a
% pagealignmacro call if that space before the closing brace is
% removed. (Generally, numeric constants should always be followed by a
% space to prevent strange expansion errors.)
\def\supereject{\par\penalty -20000\footnoteno =0 }
% @footnotestyle is meaningful for Info output only.
\let\footnotestyle=\comment
{\catcode `\@=11
%
% Auto-number footnotes. Otherwise like plain.
\gdef\footnote{%
\global\advance\footnoteno by \@ne
\edef\thisfootno{$^{\the\footnoteno}$}%
%
% In case the footnote comes at the end of a sentence, preserve the
% extra spacing after we do the footnote number.
\let\@sf\empty
\ifhmode\edef\@sf{\spacefactor\the\spacefactor}\ptexslash\fi
%
% Remove inadvertent blank space before typesetting the footnote number.
\unskip
\thisfootno\@sf
\dofootnote
}%
% Don't bother with the trickery in plain.tex to not require the
% footnote text as a parameter. Our footnotes don't need to be so general.
%
% Oh yes, they do; otherwise, @ifset (and anything else that uses
% \parseargline) fails inside footnotes because the tokens are fixed when
% the footnote is read. --karl, 16nov96.
%
\gdef\dofootnote{%
\insert\footins\bgroup
%
% Nested footnotes are not supported in TeX, that would take a lot
% more work. (\startsavinginserts does not suffice.)
\let\footnote=\errfootnotenest
%
% We want to typeset this text as a normal paragraph, even if the
% footnote reference occurs in (for example) a display environment.
% So reset some parameters.
\hsize=\txipagewidth
\interlinepenalty\interfootnotelinepenalty
\splittopskip\ht\strutbox % top baseline for broken footnotes
\splitmaxdepth\dp\strutbox
\floatingpenalty\@MM
\leftskip\z@skip
\rightskip\z@skip
\spaceskip\z@skip
\xspaceskip\z@skip
\parindent\defaultparindent
%
\smallfonts \rm
%
% Because we use hanging indentation in footnotes, a @noindent appears
% to exdent this text, so make it be a no-op. makeinfo does not use
% hanging indentation so @noindent can still be needed within footnote
% text after an @example or the like (not that this is good style).
\let\noindent = \relax
%
% Hang the footnote text off the number. Use \everypar in case the
% footnote extends for more than one paragraph.
\everypar = {\hang}%
\textindent{\thisfootno}%
%
% Don't crash into the line above the footnote text. Since this
% expands into a box, it must come within the paragraph, lest it
% provide a place where TeX can split the footnote.
\footstrut
%
% Invoke rest of plain TeX footnote routine.
\futurelet\next\fo@t
}
}%end \catcode `\@=11
\def\errfootnotenest{%
\errhelp=\EMsimple
\errmessage{Nested footnotes not supported in texinfo.tex,
even though they work in makeinfo; sorry}
}
\def\errfootnoteheading{%
\errhelp=\EMsimple
\errmessage{Footnotes in chapters, sections, etc., are not supported}
}
% In case a @footnote appears in a vbox, save the footnote text and create
% the real \insert just after the vbox finished. Otherwise, the insertion
% would be lost.
% Similarly, if a @footnote appears inside an alignment, save the footnote
% text to a box and make the \insert when a row of the table is finished.
% And the same can be done for other insert classes. --kasal, 16nov03.
%
% Replace the \insert primitive by a cheating macro.
% Deeper inside, just make sure that the saved insertions are not spilled
% out prematurely.
%
\def\startsavinginserts{%
\ifx \insert\ptexinsert
\let\insert\saveinsert
\else
\let\checkinserts\relax
\fi
}
% This \insert replacement works for both \insert\footins{foo} and
% \insert\footins\bgroup foo\egroup, but it doesn't work for \insert27{foo}.
%
\def\saveinsert#1{%
\edef\next{\noexpand\savetobox \makeSAVEname#1}%
\afterassignment\next
% swallow the left brace
\let\temp =
}
\def\makeSAVEname#1{\makecsname{SAVE\expandafter\gobble\string#1}}
\def\savetobox#1{\global\setbox#1 = \vbox\bgroup \unvbox#1}
\def\checksaveins#1{\ifvoid#1\else \placesaveins#1\fi}
\def\placesaveins#1{%
\ptexinsert \csname\expandafter\gobblesave\string#1\endcsname
{\box#1}%
}
% eat @SAVE -- beware, all of them have catcode \other:
{
\def\dospecials{\do S\do A\do V\do E} \uncatcodespecials % ;-)
\gdef\gobblesave @SAVE{}
}
% initialization:
\def\newsaveins #1{%
\edef\next{\noexpand\newsaveinsX \makeSAVEname#1}%
\next
}
\def\newsaveinsX #1{%
\csname newbox\endcsname #1%
\expandafter\def\expandafter\checkinserts\expandafter{\checkinserts
\checksaveins #1}%
}
% initialize:
\let\checkinserts\empty
\newsaveins\footins
\newsaveins\margin
% @image. We use the macros from epsf.tex to support this.
% If epsf.tex is not installed and @image is used, we complain.
%
% Check for and read epsf.tex up front. If we read it only at @image
% time, we might be inside a group, and then its definitions would get
% undone and the next image would fail.
\openin 1 = epsf.tex
\ifeof 1 \else
% Do not bother showing banner with epsf.tex v2.7k (available in
% doc/epsf.tex and on ctan).
\def\epsfannounce{\toks0 = }%
\input epsf.tex
\fi
\closein 1
%
% We will only complain once about lack of epsf.tex.
\newif\ifwarnednoepsf
\newhelp\noepsfhelp{epsf.tex must be installed for images to
work. It is also included in the Texinfo distribution, or you can get
it from https://ctan.org/texarchive/macros/texinfo/texinfo/doc/epsf.tex.}
%
\def\image#1{%
\ifx\epsfbox\thisisundefined
\ifwarnednoepsf \else
\errhelp = \noepsfhelp
\errmessage{epsf.tex not found, images will be ignored}%
\global\warnednoepsftrue
\fi
\else
\imagexxx #1,,,,,\finish
\fi
}
% Approximate height of a line in the standard text font.
\newdimen\capheight
\setbox0=\vbox{\tenrm H}
\capheight=\ht0
%
% Arguments to @image:
% #1 is (mandatory) image filename; we tack on .eps extension.
% #2 is (optional) width, #3 is (optional) height.
% #4 is (ignored optional) html alt text.
% #5 is (ignored optional) extension.
% #6 is just the usual extra ignored arg for parsing stuff.
\newif\ifimagevmode
\def\imagexxx#1,#2,#3,#4,#5,#6\finish{\begingroup
\catcode`\^^M = 5 % in case we're inside an example
\normalturnoffactive % allow _ et al. in names
\makevalueexpandable
\ifvmode
\imagevmodetrue
\medskip
% Usually we'll have text after the image which will insert
% \parskip glue, so insert it here too to equalize the space
% above and below.
\vskip\parskip
%
% Place image in a \vtop for a top page margin that is (close to) correct,
% as \topskip glue is relative to the first baseline.
\vtop\bgroup \kern -\capheight \vskip-\parskip
\fi
%
\ifx\centersub\centerV
% For @center @image, enter vertical mode and add vertical space
% Enter an extra \parskip because @center doesn't add space itself.
\vbox\bgroup\vskip\parskip\medskip\vskip\parskip
\else
% Enter horizontal mode so that indentation from an enclosing
% environment such as @quotation is respected.
% However, if we're at the top level, we don't want the
% normal paragraph indentation.
\imageindent
\fi
%
% Output the image.
\ifpdf
% For pdfTeX and LuaTeX <= 0.80
\dopdfimage{#1}{#2}{#3}%
\else
\ifx\XeTeXrevision\thisisundefined
% For epsf.tex
% \epsfbox itself resets \epsf?size at each figure.
\setbox0 = \hbox{\ignorespaces #2}%
\ifdim\wd0 > 0pt \epsfxsize=#2\relax \fi
\setbox0 = \hbox{\ignorespaces #3}%
\ifdim\wd0 > 0pt \epsfysize=#3\relax \fi
\epsfbox{#1.eps}%
\else
% For XeTeX
\doxeteximage{#1}{#2}{#3}%
\fi
\fi
%
\ifimagevmode
\egroup
\medskip % space after a standalone image
\fi
\ifx\centersub\centerV % @center @image
\medskip
\egroup % close \vbox
\fi
\endgroup}
% @float FLOATTYPE,LABEL,LOC ... @end float for displayed figures, tables,
% etc. We don't actually implement floating yet, we always include the
% float "here". But it seemed the best name for the future.
%
\envparseargdef\float{\eatcommaspace\eatcommaspace\dofloat#1, , ,\finish}
% There may be a space before second and/or third parameter; delete it.
\def\eatcommaspace#1, {#1,}
% #1 is the optional FLOATTYPE, the text label for this float, typically
% "Figure", "Table", "Example", etc. Can't contain commas. If omitted,
% this float will not be numbered and cannot be referred to.
%
% #2 is the optional xref label. Also must be present for the float to
% be referable.
%
% #3 is the optional positioning argument; for now, it is ignored. It
% will somehow specify the positions allowed to float to (here, top, bottom).
%
% We keep a separate counter for each FLOATTYPE, which we reset at each
% chapter-level command.
\let\resetallfloatnos=\empty
%
\def\dofloat#1,#2,#3,#4\finish{%
\let\thiscaption=\empty
\let\thisshortcaption=\empty
%
% don't lose footnotes inside @float.
%
% BEWARE: when the floats start float, we have to issue warning whenever an
% insert appears inside a float which could possibly float. --kasal, 26may04
%
\startsavinginserts
%
% We can't be used inside a paragraph.
\par
%
\vtop\bgroup
\def\floattype{#1}%
\def\floatlabel{#2}%
\def\floatloc{#3}% we do nothing with this yet.
%
\ifx\floattype\empty
\let\safefloattype=\empty
\else
{%
% the floattype might have accents or other special characters,
% but we need to use it in a control sequence name.
\indexnofonts
\turnoffactive
\xdef\safefloattype{\floattype}%
}%
\fi
%
% If label is given but no type, we handle that as the empty type.
\ifx\floatlabel\empty \else
% We want each FLOATTYPE to be numbered separately (Figure 1,
% Table 1, Figure 2, ...). (And if no label, no number.)
%
\expandafter\getfloatno\csname\safefloattype floatno\endcsname
\global\advance\floatno by 1
%
{%
% This magic value for \currentsection is output by \setref as the
% XREFLABEL-title value. \xrefX uses it to distinguish float
% labels (which have a completely different output format) from
% node and anchor labels. And \xrdef uses it to construct the
% lists of floats.
%
\edef\currentsection{\floatmagic=\safefloattype}%
\setref{\floatlabel}{Yfloat}%
}%
\fi
%
% start with \parskip glue, I guess.
\vskip\parskip
%
% Don't suppress indentation if a float happens to start a section.
\restorefirstparagraphindent
}
% we have these possibilities:
% @float Foo,lbl & @caption{Cap}: Foo 1.1: Cap
% @float Foo,lbl & no caption: Foo 1.1
% @float Foo & @caption{Cap}: Foo: Cap
% @float Foo & no caption: Foo
% @float ,lbl & Caption{Cap}: 1.1: Cap
% @float ,lbl & no caption: 1.1
% @float & @caption{Cap}: Cap
% @float & no caption:
%
\def\Efloat{%
\let\floatident = \empty
%
% In all cases, if we have a float type, it comes first.
\ifx\floattype\empty \else \def\floatident{\floattype}\fi
%
% If we have an xref label, the number comes next.
\ifx\floatlabel\empty \else
\ifx\floattype\empty \else % if also had float type, need tie first.
\appendtomacro\floatident{\tie}%
\fi
% the number.
\appendtomacro\floatident{\chaplevelprefix\the\floatno}%
\fi
%
% Start the printed caption with what we've constructed in
% \floatident, but keep it separate; we need \floatident again.
\let\captionline = \floatident
%
\ifx\thiscaption\empty \else
\ifx\floatident\empty \else
\appendtomacro\captionline{: }% had ident, so need a colon between
\fi
%
% caption text.
\appendtomacro\captionline{\scanexp\thiscaption}%
\fi
%
% If we have anything to print, print it, with space before.
% Eventually this needs to become an \insert.
\ifx\captionline\empty \else
\vskip.5\parskip
\captionline
%
% Space below caption.
\vskip\parskip
\fi
%
% If have an xref label, write the list of floats info. Do this
% after the caption, to avoid chance of it being a breakpoint.
\ifx\floatlabel\empty \else
% Write the text that goes in the lof to the aux file as
% \floatlabel-lof. Besides \floatident, we include the short
% caption if specified, else the full caption if specified, else nothing.
{%
\requireauxfile
\atdummies
%
\ifx\thisshortcaption\empty
\def\gtemp{\thiscaption}%
\else
\def\gtemp{\thisshortcaption}%
\fi
\immediate\write\auxfile{@xrdef{\floatlabel-lof}{\floatident
\ifx\gtemp\empty \else : \gtemp \fi}}%
}%
\fi
\egroup % end of \vtop
%
\checkinserts
}
% Append the tokens #2 to the definition of macro #1, not expanding either.
%
\def\appendtomacro#1#2{%
\expandafter\def\expandafter#1\expandafter{#1#2}%
}
% @caption, @shortcaption
%
\def\caption{\docaption\thiscaption}
\def\shortcaption{\docaption\thisshortcaption}
\def\docaption{\checkenv\float \bgroup\scanctxt\docaptionz}
\def\docaptionz#1#2{\egroup \def#1{#2}}
% The parameter is the control sequence identifying the counter we are
% going to use. Create it if it doesn't exist and assign it to \floatno.
\def\getfloatno#1{%
\ifx#1\relax
% Haven't seen this figure type before.
\csname newcount\endcsname #1%
%
% Remember to reset this floatno at the next chap.
\expandafter\gdef\expandafter\resetallfloatnos
\expandafter{\resetallfloatnos #1=0 }%
\fi
\let\floatno#1%
}
% \setref calls this to get the XREFLABEL-snt value. We want an @xref
% to the FLOATLABEL to expand to "Figure 3.1". We call \setref when we
% first read the @float command.
%
\def\Yfloat{\floattype@tie \chaplevelprefix\the\floatno}%
% Magic string used for the XREFLABEL-title value, so \xrefX can
% distinguish floats from other xref types.
\def\floatmagic{!!float!!}
% #1 is the control sequence we are passed; we expand into a conditional
% which is true if #1 represents a float ref. That is, the magic
% \currentsection value which we \setref above.
%
\def\iffloat#1{\expandafter\doiffloat#1==\finish}
%
% #1 is (maybe) the \floatmagic string. If so, #2 will be the
% (safe) float type for this float. We set \iffloattype to #2.
%
\def\doiffloat#1=#2=#3\finish{%
\def\temp{#1}%
\def\iffloattype{#2}%
\ifx\temp\floatmagic
}
% @listoffloats FLOATTYPE - print a list of floats like a table of contents.
%
\parseargdef\listoffloats{%
\def\floattype{#1}% floattype
{%
% the floattype might have accents or other special characters,
% but we need to use it in a control sequence name.
\indexnofonts
\turnoffactive
\xdef\safefloattype{\floattype}%
}%
%
% \xrdef saves the floats as a \do-list in \floatlistSAFEFLOATTYPE.
\expandafter\ifx\csname floatlist\safefloattype\endcsname \relax
\ifhavexrefs
% if the user said @listoffloats foo but never @float foo.
\message{\linenumber No `\safefloattype' floats to list.}%
\fi
\else
\begingroup
\leftskip=\tocindent % indent these entries like a toc
\let\do=\listoffloatsdo
\csname floatlist\safefloattype\endcsname
\endgroup
\fi
}
% This is called on each entry in a list of floats. We're passed the
% xref label, in the form LABEL-title, which is how we save it in the
% aux file. We strip off the -title and look up \XRLABEL-lof, which
% has the text we're supposed to typeset here.
%
% Figures without xref labels will not be included in the list (since
% they won't appear in the aux file).
%
\def\listoffloatsdo#1{\listoffloatsdoentry#1\finish}
\def\listoffloatsdoentry#1-title\finish{{%
% Can't fully expand XR#1-lof because it can contain anything. Just
% pass the control sequence. On the other hand, XR#1-pg is just the
% page number, and we want to fully expand that so we can get a link
% in pdf output.
\toksA = \expandafter{\csname XR#1-lof\endcsname}%
%
% use the same \entry macro we use to generate the TOC and index.
\edef\writeentry{\noexpand\entry{\the\toksA}{\csname XR#1-pg\endcsname}}%
\writeentry
}}
\message{localization,}
% For single-language documents, @documentlanguage is usually given very
% early, just after @documentencoding. Single argument is the language
% (de) or locale (de_DE) abbreviation.
%
{
\catcode`\_ = \active
\globaldefs=1
\parseargdef\documentlanguage{%
\tex % read txi-??.tex file in plain TeX.
% Read the file by the name they passed if it exists.
\let_ = \normalunderscore % normal _ character for filename test
\openin 1 txi-#1.tex
\ifeof 1
\documentlanguagetrywithoutunderscore #1_\finish
\else
\globaldefs = 1 % everything in the txi-LL files needs to persist
\input txi-#1.tex
\fi
\closein 1
\endgroup % end raw TeX
}
%
% If they passed de_DE, and txi-de_DE.tex doesn't exist,
% try txi-de.tex.
%
\gdef\documentlanguagetrywithoutunderscore#1_#2\finish{%
\openin 1 txi-#1.tex
\ifeof 1
\errhelp = \nolanghelp
\errmessage{Cannot read language file txi-#1.tex}%
\else
\globaldefs = 1 % everything in the txi-LL files needs to persist
\input txi-#1.tex
\fi
\closein 1
}
}% end of special _ catcode
%
\newhelp\nolanghelp{The given language definition file cannot be found or
is empty. Maybe you need to install it? Putting it in the current
directory should work if nowhere else does.}
% This macro is called from txi-??.tex files; the first argument is the
% \language name to set (without the "\lang@" prefix), the second and
% third args are \{left,right}hyphenmin.
%
% The language names to pass are determined when the format is built.
% See the etex.log file created at that time, e.g.,
% /usr/local/texlive/2008/texmf-var/web2c/pdftex/etex.log.
%
% With TeX Live 2008, etex now includes hyphenation patterns for all
% available languages. This means we can support hyphenation in
% Texinfo, at least to some extent. (This still doesn't solve the
% accented characters problem.)
%
\catcode`@=11
\def\txisetlanguage#1#2#3{%
% do not set the language if the name is undefined in the current TeX.
\expandafter\ifx\csname lang@#1\endcsname \relax
\message{no patterns for #1}%
\else
\global\language = \csname lang@#1\endcsname
\fi
% but there is no harm in adjusting the hyphenmin values regardless.
\global\lefthyphenmin = #2\relax
\global\righthyphenmin = #3\relax
}
% XeTeX and LuaTeX can handle Unicode natively.
% Their default I/O uses UTF-8 sequences instead of a byte-wise operation.
% Other TeX engines' I/O (pdfTeX, etc.) is byte-wise.
%
\newif\iftxinativeunicodecapable
\newif\iftxiusebytewiseio
\ifx\XeTeXrevision\thisisundefined
\ifx\luatexversion\thisisundefined
\txinativeunicodecapablefalse
\txiusebytewiseiotrue
\else
\txinativeunicodecapabletrue
\txiusebytewiseiofalse
\fi
\else
\txinativeunicodecapabletrue
\txiusebytewiseiofalse
\fi
% Set I/O by bytes instead of UTF-8 sequence for XeTeX and LuaTex
% for non-UTF-8 (byte-wise) encodings.
%
\def\setbytewiseio{%
\ifx\XeTeXrevision\thisisundefined
\else
\XeTeXdefaultencoding "bytes" % For subsequent files to be read
\XeTeXinputencoding "bytes" % For document root file
% Unfortunately, there seems to be no corresponding XeTeX command for
% output encoding. This is a problem for auxiliary index and TOC files.
% The only solution would be perhaps to write out @U{...} sequences in
% place of non-ASCII characters.
\fi
\ifx\luatexversion\thisisundefined
\else
\directlua{
local utf8_char, byte, gsub = unicode.utf8.char, string.byte, string.gsub
local function convert_char (char)
return utf8_char(byte(char))
end
local function convert_line (line)
return gsub(line, ".", convert_char)
end
callback.register("process_input_buffer", convert_line)
local function convert_line_out (line)
local line_out = ""
for c in string.utfvalues(line) do
line_out = line_out .. string.char(c)
end
return line_out
end
callback.register("process_output_buffer", convert_line_out)
}
\fi
\txiusebytewiseiotrue
}
% Helpers for encodings.
% Set the catcode of characters 128 through 255 to the specified number.
%
\def\setnonasciicharscatcode#1{%
\count255=128
\loop\ifnum\count255<256
\global\catcode\count255=#1\relax
\advance\count255 by 1
\repeat
}
\def\setnonasciicharscatcodenonglobal#1{%
\count255=128
\loop\ifnum\count255<256
\catcode\count255=#1\relax
\advance\count255 by 1
\repeat
}
% @documentencoding sets the definition of non-ASCII characters
% according to the specified encoding.
%
\def\documentencoding{\parseargusing\filenamecatcodes\documentencodingzzz}
\def\documentencodingzzz#1{%
%
% Encoding being declared for the document.
\def\declaredencoding{\csname #1.enc\endcsname}%
%
% Supported encodings: names converted to tokens in order to be able
% to compare them with \ifx.
\def\ascii{\csname US-ASCII.enc\endcsname}%
\def\latnine{\csname ISO-8859-15.enc\endcsname}%
\def\latone{\csname ISO-8859-1.enc\endcsname}%
\def\lattwo{\csname ISO-8859-2.enc\endcsname}%
\def\utfeight{\csname UTF-8.enc\endcsname}%
%
\ifx \declaredencoding \ascii
\asciichardefs
%
\else \ifx \declaredencoding \lattwo
\iftxinativeunicodecapable
\setbytewiseio
\fi
\setnonasciicharscatcode\active
\lattwochardefs
%
\else \ifx \declaredencoding \latone
\iftxinativeunicodecapable
\setbytewiseio
\fi
\setnonasciicharscatcode\active
\latonechardefs
%
\else \ifx \declaredencoding \latnine
\iftxinativeunicodecapable
\setbytewiseio
\fi
\setnonasciicharscatcode\active
\latninechardefs
%
\else \ifx \declaredencoding \utfeight
\iftxinativeunicodecapable
% For native Unicode handling (XeTeX and LuaTeX)
\nativeunicodechardefs
\else
% For treating UTF-8 as byte sequences (TeX, eTeX and pdfTeX).
% Since we already invoke \utfeightchardefs at the top level,
% making non-ascii chars active is sufficient.
\setnonasciicharscatcode\active
\fi
%
\else
\message{Ignoring unknown document encoding: #1.}%
%
\fi % utfeight
\fi % latnine
\fi % latone
\fi % lattwo
\fi % ascii
%
\ifx\XeTeXrevision\thisisundefined
\else
\ifx \declaredencoding \utfeight
\else
\ifx \declaredencoding \ascii
\else
\message{Warning: XeTeX with non-UTF-8 encodings cannot handle %
non-ASCII characters in auxiliary files.}%
\fi
\fi
\fi
}
% A message to be logged when using a character that isn't available
% the default font encoding (OT1).
%
\def\missingcharmsg#1{\message{Character missing, sorry: #1.}}
% Take account of \c (plain) vs. \, (Texinfo) difference.
\def\cedilla#1{\ifx\c\ptexc\c{#1}\else\,{#1}\fi}
\def\gdefchar#1#2{%
\gdef#1{%
\ifpassthroughchars
\string#1%
\else
#2%
\fi
}}
\begingroup
% Make non-ASCII characters active for defining the character definition
% macros.
\setnonasciicharscatcode\active
% Latin1 (ISO-8859-1) character definitions.
\gdef\latonechardefs{%
\gdefchar^^a0{\tie}
\gdefchar^^a1{\exclamdown}
\gdefchar^^a2{{\tcfont \char162}} % cent
\gdefchar^^a3{\pounds{}}
\gdefchar^^a4{{\tcfont \char164}} % currency
\gdefchar^^a5{{\tcfont \char165}} % yen
\gdefchar^^a6{{\tcfont \char166}} % broken bar
\gdefchar^^a7{\S}
\gdefchar^^a8{\"{}}
\gdefchar^^a9{\copyright{}}
\gdefchar^^aa{\ordf}
\gdefchar^^ab{\guillemetleft{}}
\gdefchar^^ac{\ensuremath\lnot}
\gdefchar^^ad{\-}
\gdefchar^^ae{\registeredsymbol{}}
\gdefchar^^af{\={}}
%
\gdefchar^^b0{\textdegree}
\gdefchar^^b1{$\pm$}
\gdefchar^^b2{$^2$}
\gdefchar^^b3{$^3$}
\gdefchar^^b4{\'{}}
\gdefchar^^b5{$\mu$}
\gdefchar^^b6{\P}
\gdefchar^^b7{\ensuremath\cdot}
\gdefchar^^b8{\cedilla\ }
\gdefchar^^b9{$^1$}
\gdefchar^^ba{\ordm}
\gdefchar^^bb{\guillemetright{}}
\gdefchar^^bc{$1\over4$}
\gdefchar^^bd{$1\over2$}
\gdefchar^^be{$3\over4$}
\gdefchar^^bf{\questiondown}
%
\gdefchar^^c0{\`A}
\gdefchar^^c1{\'A}
\gdefchar^^c2{\^A}
\gdefchar^^c3{\~A}
\gdefchar^^c4{\"A}
\gdefchar^^c5{\ringaccent A}
\gdefchar^^c6{\AE}
\gdefchar^^c7{\cedilla C}
\gdefchar^^c8{\`E}
\gdefchar^^c9{\'E}
\gdefchar^^ca{\^E}
\gdefchar^^cb{\"E}
\gdefchar^^cc{\`I}
\gdefchar^^cd{\'I}
\gdefchar^^ce{\^I}
\gdefchar^^cf{\"I}
%
\gdefchar^^d0{\DH}
\gdefchar^^d1{\~N}
\gdefchar^^d2{\`O}
\gdefchar^^d3{\'O}
\gdefchar^^d4{\^O}
\gdefchar^^d5{\~O}
\gdefchar^^d6{\"O}
\gdefchar^^d7{$\times$}
\gdefchar^^d8{\O}
\gdefchar^^d9{\`U}
\gdefchar^^da{\'U}
\gdefchar^^db{\^U}
\gdefchar^^dc{\"U}
\gdefchar^^dd{\'Y}
\gdefchar^^de{\TH}
\gdefchar^^df{\ss}
%
\gdefchar^^e0{\`a}
\gdefchar^^e1{\'a}
\gdefchar^^e2{\^a}
\gdefchar^^e3{\~a}
\gdefchar^^e4{\"a}
\gdefchar^^e5{\ringaccent a}
\gdefchar^^e6{\ae}
\gdefchar^^e7{\cedilla c}
\gdefchar^^e8{\`e}
\gdefchar^^e9{\'e}
\gdefchar^^ea{\^e}
\gdefchar^^eb{\"e}
\gdefchar^^ec{\`{\dotless i}}
\gdefchar^^ed{\'{\dotless i}}
\gdefchar^^ee{\^{\dotless i}}
\gdefchar^^ef{\"{\dotless i}}
%
\gdefchar^^f0{\dh}
\gdefchar^^f1{\~n}
\gdefchar^^f2{\`o}
\gdefchar^^f3{\'o}
\gdefchar^^f4{\^o}
\gdefchar^^f5{\~o}
\gdefchar^^f6{\"o}
\gdefchar^^f7{$\div$}
\gdefchar^^f8{\o}
\gdefchar^^f9{\`u}
\gdefchar^^fa{\'u}
\gdefchar^^fb{\^u}
\gdefchar^^fc{\"u}
\gdefchar^^fd{\'y}
\gdefchar^^fe{\th}
\gdefchar^^ff{\"y}
}
% Latin9 (ISO-8859-15) encoding character definitions.
\gdef\latninechardefs{%
% Encoding is almost identical to Latin1.
\latonechardefs
%
\gdefchar^^a4{\euro{}}
\gdefchar^^a6{\v S}
\gdefchar^^a8{\v s}
\gdefchar^^b4{\v Z}
\gdefchar^^b8{\v z}
\gdefchar^^bc{\OE}
\gdefchar^^bd{\oe}
\gdefchar^^be{\"Y}
}
% Latin2 (ISO-8859-2) character definitions.
\gdef\lattwochardefs{%
\gdefchar^^a0{\tie}
\gdefchar^^a1{\ogonek{A}}
\gdefchar^^a2{\u{}}
\gdefchar^^a3{\L}
\gdefchar^^a4{\missingcharmsg{CURRENCY SIGN}}
\gdefchar^^a5{\v L}
\gdefchar^^a6{\'S}
\gdefchar^^a7{\S}
\gdefchar^^a8{\"{}}
\gdefchar^^a9{\v S}
\gdefchar^^aa{\cedilla S}
\gdefchar^^ab{\v T}
\gdefchar^^ac{\'Z}
\gdefchar^^ad{\-}
\gdefchar^^ae{\v Z}
\gdefchar^^af{\dotaccent Z}
%
\gdefchar^^b0{\textdegree}
\gdefchar^^b1{\ogonek{a}}
\gdefchar^^b2{\ogonek{ }}
\gdefchar^^b3{\l}
\gdefchar^^b4{\'{}}
\gdefchar^^b5{\v l}
\gdefchar^^b6{\'s}
\gdefchar^^b7{\v{}}
\gdefchar^^b8{\cedilla\ }
\gdefchar^^b9{\v s}
\gdefchar^^ba{\cedilla s}
\gdefchar^^bb{\v t}
\gdefchar^^bc{\'z}
\gdefchar^^bd{\H{}}
\gdefchar^^be{\v z}
\gdefchar^^bf{\dotaccent z}
%
\gdefchar^^c0{\'R}
\gdefchar^^c1{\'A}
\gdefchar^^c2{\^A}
\gdefchar^^c3{\u A}
\gdefchar^^c4{\"A}
\gdefchar^^c5{\'L}
\gdefchar^^c6{\'C}
\gdefchar^^c7{\cedilla C}
\gdefchar^^c8{\v C}
\gdefchar^^c9{\'E}
\gdefchar^^ca{\ogonek{E}}
\gdefchar^^cb{\"E}
\gdefchar^^cc{\v E}
\gdefchar^^cd{\'I}
\gdefchar^^ce{\^I}
\gdefchar^^cf{\v D}
%
\gdefchar^^d0{\DH}
\gdefchar^^d1{\'N}
\gdefchar^^d2{\v N}
\gdefchar^^d3{\'O}
\gdefchar^^d4{\^O}
\gdefchar^^d5{\H O}
\gdefchar^^d6{\"O}
\gdefchar^^d7{$\times$}
\gdefchar^^d8{\v R}
\gdefchar^^d9{\ringaccent U}
\gdefchar^^da{\'U}
\gdefchar^^db{\H U}
\gdefchar^^dc{\"U}
\gdefchar^^dd{\'Y}
\gdefchar^^de{\cedilla T}
\gdefchar^^df{\ss}
%
\gdefchar^^e0{\'r}
\gdefchar^^e1{\'a}
\gdefchar^^e2{\^a}
\gdefchar^^e3{\u a}
\gdefchar^^e4{\"a}
\gdefchar^^e5{\'l}
\gdefchar^^e6{\'c}
\gdefchar^^e7{\cedilla c}
\gdefchar^^e8{\v c}
\gdefchar^^e9{\'e}
\gdefchar^^ea{\ogonek{e}}
\gdefchar^^eb{\"e}
\gdefchar^^ec{\v e}
\gdefchar^^ed{\'{\dotless{i}}}
\gdefchar^^ee{\^{\dotless{i}}}
\gdefchar^^ef{\v d}
%
\gdefchar^^f0{\dh}
\gdefchar^^f1{\'n}
\gdefchar^^f2{\v n}
\gdefchar^^f3{\'o}
\gdefchar^^f4{\^o}
\gdefchar^^f5{\H o}
\gdefchar^^f6{\"o}
\gdefchar^^f7{$\div$}
\gdefchar^^f8{\v r}
\gdefchar^^f9{\ringaccent u}
\gdefchar^^fa{\'u}
\gdefchar^^fb{\H u}
\gdefchar^^fc{\"u}
\gdefchar^^fd{\'y}
\gdefchar^^fe{\cedilla t}
\gdefchar^^ff{\dotaccent{}}
}
\endgroup % active chars
% UTF-8 character definitions.
%
% This code to support UTF-8 is based on LaTeX's utf8.def, with some
% changes for Texinfo conventions. It is included here under the GPL by
% permission from Frank Mittelbach and the LaTeX team.
%
\newcount\countUTFx
\newcount\countUTFy
\newcount\countUTFz
\gdef\UTFviiiTwoOctets#1#2{\expandafter
\UTFviiiDefined\csname u8:#1\string #2\endcsname}
%
\gdef\UTFviiiThreeOctets#1#2#3{\expandafter
\UTFviiiDefined\csname u8:#1\string #2\string #3\endcsname}
%
\gdef\UTFviiiFourOctets#1#2#3#4{\expandafter
\UTFviiiDefined\csname u8:#1\string #2\string #3\string #4\endcsname}
\gdef\UTFviiiDefined#1{%
\ifx #1\relax
\message{\linenumber Unicode char \string #1 not defined for Texinfo}%
\else
\expandafter #1%
\fi
}
% Give non-ASCII bytes the active definitions for processing UTF-8 sequences
\begingroup
\catcode`\~13
\catcode`\$12
\catcode`\"12
% Loop from \countUTFx to \countUTFy, performing \UTFviiiTmp
% substituting ~ and $ with a character token of that value.
\def\UTFviiiLoop{%
\global\catcode\countUTFx\active
\uccode`\~\countUTFx
\uccode`\$\countUTFx
\uppercase\expandafter{\UTFviiiTmp}%
\advance\countUTFx by 1
\ifnum\countUTFx < \countUTFy
\expandafter\UTFviiiLoop
\fi}
% For bytes other than the first in a UTF-8 sequence. Not expected to
% be expanded except when writing to auxiliary files.
\countUTFx = "80
\countUTFy = "C2
\def\UTFviiiTmp{%
\gdef~{%
\ifpassthroughchars $\fi}}%
\UTFviiiLoop
\countUTFx = "C2
\countUTFy = "E0
\def\UTFviiiTmp{%
\gdef~{%
\ifpassthroughchars $%
\else\expandafter\UTFviiiTwoOctets\expandafter$\fi}}%
\UTFviiiLoop
\countUTFx = "E0
\countUTFy = "F0
\def\UTFviiiTmp{%
\gdef~{%
\ifpassthroughchars $%
\else\expandafter\UTFviiiThreeOctets\expandafter$\fi}}%
\UTFviiiLoop
\countUTFx = "F0
\countUTFy = "F4
\def\UTFviiiTmp{%
\gdef~{%
\ifpassthroughchars $%
\else\expandafter\UTFviiiFourOctets\expandafter$\fi
}}%
\UTFviiiLoop
\endgroup
\def\globallet{\global\let} % save some \expandafter's below
% @U{xxxx} to produce U+xxxx, if we support it.
\def\U#1{%
\expandafter\ifx\csname uni:#1\endcsname \relax
\iftxinativeunicodecapable
% All Unicode characters can be used if native Unicode handling is
% active. However, if the font does not have the glyph,
% letters are missing.
\begingroup
\uccode`\.="#1\relax
\uppercase{.}
\endgroup
\else
\errhelp = \EMsimple
\errmessage{Unicode character U+#1 not supported, sorry}%
\fi
\else
\csname uni:#1\endcsname
\fi
}
% These macros are used here to construct the name of a control
% sequence to be defined.
\def\UTFviiiTwoOctetsName#1#2{%
\csname u8:#1\string #2\endcsname}%
\def\UTFviiiThreeOctetsName#1#2#3{%
\csname u8:#1\string #2\string #3\endcsname}%
\def\UTFviiiFourOctetsName#1#2#3#4{%
\csname u8:#1\string #2\string #3\string #4\endcsname}%
% For UTF-8 byte sequences (TeX, e-TeX and pdfTeX),
% provide a definition macro to replace a Unicode character;
% this gets used by the @U command
%
\begingroup
\catcode`\"=12
\catcode`\<=12
\catcode`\.=12
\catcode`\,=12
\catcode`\;=12
\catcode`\!=12
\catcode`\~=13
\gdef\DeclareUnicodeCharacterUTFviii#1#2{%
\countUTFz = "#1\relax
\begingroup
\parseXMLCharref
% Give \u8:... its definition. The sequence of seven \expandafter's
% expands after the \gdef three times, e.g.
%
% 1. \UTFviiTwoOctetsName B1 B2
% 2. \csname u8:B1 \string B2 \endcsname
% 3. \u8: B1 B2 (a single control sequence token)
%
\expandafter\expandafter
\expandafter\expandafter
\expandafter\expandafter
\expandafter\gdef \UTFviiiTmp{#2}%
%
\expandafter\ifx\csname uni:#1\endcsname \relax \else
\message{Internal error, already defined: #1}%
\fi
%
% define an additional control sequence for this code point.
\expandafter\globallet\csname uni:#1\endcsname \UTFviiiTmp
\endgroup}
%
% Given the value in \countUTFz as a Unicode code point, set \UTFviiiTmp
% to the corresponding UTF-8 sequence.
\gdef\parseXMLCharref{%
\ifnum\countUTFz < "20\relax
\errhelp = \EMsimple
\errmessage{Cannot define Unicode char value < 0020}%
\else\ifnum\countUTFz < "800\relax
\parseUTFviiiA,%
\parseUTFviiiB C\UTFviiiTwoOctetsName.,%
\else\ifnum\countUTFz < "10000\relax
\parseUTFviiiA;%
\parseUTFviiiA,%
\parseUTFviiiB E\UTFviiiThreeOctetsName.{,;}%
\else
\parseUTFviiiA;%
\parseUTFviiiA,%
\parseUTFviiiA!%
\parseUTFviiiB F\UTFviiiFourOctetsName.{!,;}%
\fi\fi\fi
}
% Extract a byte from the end of the UTF-8 representation of \countUTFx.
% It must be a non-initial byte in the sequence.
% Change \uccode of #1 for it to be used in \parseUTFviiiB as one
% of the bytes.
\gdef\parseUTFviiiA#1{%
\countUTFx = \countUTFz
\divide\countUTFz by 64
\countUTFy = \countUTFz % Save to be the future value of \countUTFz.
\multiply\countUTFz by 64
% \countUTFz is now \countUTFx with the last 5 bits cleared. Subtract
% in order to get the last five bits.
\advance\countUTFx by -\countUTFz
% Convert this to the byte in the UTF-8 sequence.
\advance\countUTFx by 128
\uccode `#1\countUTFx
\countUTFz = \countUTFy}
% Used to put a UTF-8 byte sequence into \UTFviiiTmp
% #1 is the increment for \countUTFz to yield a the first byte of the UTF-8
% sequence.
% #2 is one of the \UTFviii*OctetsName macros.
% #3 is always a full stop (.)
% #4 is a template for the other bytes in the sequence. The values for these
% bytes is substituted in here with \uppercase using the \uccode's.
\gdef\parseUTFviiiB#1#2#3#4{%
\advance\countUTFz by "#10\relax
\uccode `#3\countUTFz
\uppercase{\gdef\UTFviiiTmp{#2#3#4}}}
\endgroup
% For native Unicode handling (XeTeX and LuaTeX),
% provide a definition macro that sets a catcode to `other' non-globally
%
\def\DeclareUnicodeCharacterNativeOther#1#2{%
\catcode"#1=\other
}
% https://en.wikipedia.org/wiki/Plane_(Unicode)#Basic_M
% U+0000..U+007F = https://en.wikipedia.org/wiki/Basic_Latin_(Unicode_block)
% U+0080..U+00FF = https://en.wikipedia.org/wiki/Latin-1_Supplement_(Unicode_block)
% U+0100..U+017F = https://en.wikipedia.org/wiki/Latin_Extended-A
% U+0180..U+024F = https://en.wikipedia.org/wiki/Latin_Extended-B
%
% Many of our renditions are less than wonderful, and all the missing
% characters are available somewhere. Loading the necessary fonts
% awaits user request. We can't truly support Unicode without
% reimplementing everything that's been done in LaTeX for many years,
% plus probably using luatex or xetex, and who knows what else.
% We won't be doing that here in this simple file. But we can try to at
% least make most of the characters not bomb out.
%
\def\unicodechardefs{%
\DeclareUnicodeCharacter{0020}{ } % space
\DeclareUnicodeCharacter{0021}{\char"21 }% % space to terminate number
\DeclareUnicodeCharacter{0022}{\char"22 }%
\DeclareUnicodeCharacter{0023}{\char"23 }%
\DeclareUnicodeCharacter{0024}{\char"24 }%
\DeclareUnicodeCharacter{0025}{\char"25 }%
\DeclareUnicodeCharacter{0026}{\char"26 }%
\DeclareUnicodeCharacter{0027}{\char"27 }%
\DeclareUnicodeCharacter{0028}{\char"28 }%
\DeclareUnicodeCharacter{0029}{\char"29 }%
\DeclareUnicodeCharacter{002A}{\char"2A }%
\DeclareUnicodeCharacter{002B}{\char"2B }%
\DeclareUnicodeCharacter{002C}{\char"2C }%
\DeclareUnicodeCharacter{002D}{\char"2D }%
\DeclareUnicodeCharacter{002E}{\char"2E }%
\DeclareUnicodeCharacter{002F}{\char"2F }%
\DeclareUnicodeCharacter{0030}{0}%
\DeclareUnicodeCharacter{0031}{1}%
\DeclareUnicodeCharacter{0032}{2}%
\DeclareUnicodeCharacter{0033}{3}%
\DeclareUnicodeCharacter{0034}{4}%
\DeclareUnicodeCharacter{0035}{5}%
\DeclareUnicodeCharacter{0036}{6}%
\DeclareUnicodeCharacter{0037}{7}%
\DeclareUnicodeCharacter{0038}{8}%
\DeclareUnicodeCharacter{0039}{9}%
\DeclareUnicodeCharacter{003A}{\char"3A }%
\DeclareUnicodeCharacter{003B}{\char"3B }%
\DeclareUnicodeCharacter{003C}{\char"3C }%
\DeclareUnicodeCharacter{003D}{\char"3D }%
\DeclareUnicodeCharacter{003E}{\char"3E }%
\DeclareUnicodeCharacter{003F}{\char"3F }%
\DeclareUnicodeCharacter{0040}{\char"40 }%
\DeclareUnicodeCharacter{0041}{A}%
\DeclareUnicodeCharacter{0042}{B}%
\DeclareUnicodeCharacter{0043}{C}%
\DeclareUnicodeCharacter{0044}{D}%
\DeclareUnicodeCharacter{0045}{E}%
\DeclareUnicodeCharacter{0046}{F}%
\DeclareUnicodeCharacter{0047}{G}%
\DeclareUnicodeCharacter{0048}{H}%
\DeclareUnicodeCharacter{0049}{I}%
\DeclareUnicodeCharacter{004A}{J}%
\DeclareUnicodeCharacter{004B}{K}%
\DeclareUnicodeCharacter{004C}{L}%
\DeclareUnicodeCharacter{004D}{M}%
\DeclareUnicodeCharacter{004E}{N}%
\DeclareUnicodeCharacter{004F}{O}%
\DeclareUnicodeCharacter{0050}{P}%
\DeclareUnicodeCharacter{0051}{Q}%
\DeclareUnicodeCharacter{0052}{R}%
\DeclareUnicodeCharacter{0053}{S}%
\DeclareUnicodeCharacter{0054}{T}%
\DeclareUnicodeCharacter{0055}{U}%
\DeclareUnicodeCharacter{0056}{V}%
\DeclareUnicodeCharacter{0057}{W}%
\DeclareUnicodeCharacter{0058}{X}%
\DeclareUnicodeCharacter{0059}{Y}%
\DeclareUnicodeCharacter{005A}{Z}%
\DeclareUnicodeCharacter{005B}{\char"5B }%
\DeclareUnicodeCharacter{005C}{\char"5C }%
\DeclareUnicodeCharacter{005D}{\char"5D }%
\DeclareUnicodeCharacter{005E}{\char"5E }%
\DeclareUnicodeCharacter{005F}{\char"5F }%
\DeclareUnicodeCharacter{0060}{\char"60 }%
\DeclareUnicodeCharacter{0061}{a}%
\DeclareUnicodeCharacter{0062}{b}%
\DeclareUnicodeCharacter{0063}{c}%
\DeclareUnicodeCharacter{0064}{d}%
\DeclareUnicodeCharacter{0065}{e}%
\DeclareUnicodeCharacter{0066}{f}%
\DeclareUnicodeCharacter{0067}{g}%
\DeclareUnicodeCharacter{0068}{h}%
\DeclareUnicodeCharacter{0069}{i}%
\DeclareUnicodeCharacter{006A}{j}%
\DeclareUnicodeCharacter{006B}{k}%
\DeclareUnicodeCharacter{006C}{l}%
\DeclareUnicodeCharacter{006D}{m}%
\DeclareUnicodeCharacter{006E}{n}%
\DeclareUnicodeCharacter{006F}{o}%
\DeclareUnicodeCharacter{0070}{p}%
\DeclareUnicodeCharacter{0071}{q}%
\DeclareUnicodeCharacter{0072}{r}%
\DeclareUnicodeCharacter{0073}{s}%
\DeclareUnicodeCharacter{0074}{t}%
\DeclareUnicodeCharacter{0075}{u}%
\DeclareUnicodeCharacter{0076}{v}%
\DeclareUnicodeCharacter{0077}{w}%
\DeclareUnicodeCharacter{0078}{x}%
\DeclareUnicodeCharacter{0079}{y}%
\DeclareUnicodeCharacter{007A}{z}%
\DeclareUnicodeCharacter{007B}{\char"7B }%
\DeclareUnicodeCharacter{007C}{\char"7C }%
\DeclareUnicodeCharacter{007D}{\char"7D }%
\DeclareUnicodeCharacter{007E}{\char"7E }%
% \DeclareUnicodeCharacter{007F}{} % DEL
%
\DeclareUnicodeCharacter{00A0}{\tie}%
\DeclareUnicodeCharacter{00A1}{\exclamdown}%
\DeclareUnicodeCharacter{00A2}{{\tcfont \char162}}% 0242=cent
\DeclareUnicodeCharacter{00A3}{\pounds{}}%
\DeclareUnicodeCharacter{00A4}{{\tcfont \char164}}% 0244=currency
\DeclareUnicodeCharacter{00A5}{{\tcfont \char165}}% 0245=yen
\DeclareUnicodeCharacter{00A6}{{\tcfont \char166}}% 0246=brokenbar
\DeclareUnicodeCharacter{00A7}{\S}%
\DeclareUnicodeCharacter{00A8}{\"{ }}%
\DeclareUnicodeCharacter{00A9}{\copyright{}}%
\DeclareUnicodeCharacter{00AA}{\ordf}%
\DeclareUnicodeCharacter{00AB}{\guillemetleft{}}%
\DeclareUnicodeCharacter{00AC}{\ensuremath\lnot}%
\DeclareUnicodeCharacter{00AD}{\-}%
\DeclareUnicodeCharacter{00AE}{\registeredsymbol{}}%
\DeclareUnicodeCharacter{00AF}{\={ }}%
%
\DeclareUnicodeCharacter{00B0}{\textdegree}%
\DeclareUnicodeCharacter{00B1}{\ensuremath\pm}%
\DeclareUnicodeCharacter{00B2}{$^2$}%
\DeclareUnicodeCharacter{00B3}{$^3$}%
\DeclareUnicodeCharacter{00B4}{\'{ }}%
\DeclareUnicodeCharacter{00B5}{$\mu$}%
\DeclareUnicodeCharacter{00B6}{\P}%
\DeclareUnicodeCharacter{00B7}{\ensuremath\cdot}%
\DeclareUnicodeCharacter{00B8}{\cedilla{ }}%
\DeclareUnicodeCharacter{00B9}{$^1$}%
\DeclareUnicodeCharacter{00BA}{\ordm}%
\DeclareUnicodeCharacter{00BB}{\guillemetright{}}%
\DeclareUnicodeCharacter{00BC}{$1\over4$}%
\DeclareUnicodeCharacter{00BD}{$1\over2$}%
\DeclareUnicodeCharacter{00BE}{$3\over4$}%
\DeclareUnicodeCharacter{00BF}{\questiondown}%
%
\DeclareUnicodeCharacter{00C0}{\`A}%
\DeclareUnicodeCharacter{00C1}{\'A}%
\DeclareUnicodeCharacter{00C2}{\^A}%
\DeclareUnicodeCharacter{00C3}{\~A}%
\DeclareUnicodeCharacter{00C4}{\"A}%
\DeclareUnicodeCharacter{00C5}{\AA}%
\DeclareUnicodeCharacter{00C6}{\AE}%
\DeclareUnicodeCharacter{00C7}{\cedilla{C}}%
\DeclareUnicodeCharacter{00C8}{\`E}%
\DeclareUnicodeCharacter{00C9}{\'E}%
\DeclareUnicodeCharacter{00CA}{\^E}%
\DeclareUnicodeCharacter{00CB}{\"E}%
\DeclareUnicodeCharacter{00CC}{\`I}%
\DeclareUnicodeCharacter{00CD}{\'I}%
\DeclareUnicodeCharacter{00CE}{\^I}%
\DeclareUnicodeCharacter{00CF}{\"I}%
%
\DeclareUnicodeCharacter{00D0}{\DH}%
\DeclareUnicodeCharacter{00D1}{\~N}%
\DeclareUnicodeCharacter{00D2}{\`O}%
\DeclareUnicodeCharacter{00D3}{\'O}%
\DeclareUnicodeCharacter{00D4}{\^O}%
\DeclareUnicodeCharacter{00D5}{\~O}%
\DeclareUnicodeCharacter{00D6}{\"O}%
\DeclareUnicodeCharacter{00D7}{\ensuremath\times}%
\DeclareUnicodeCharacter{00D8}{\O}%
\DeclareUnicodeCharacter{00D9}{\`U}%
\DeclareUnicodeCharacter{00DA}{\'U}%
\DeclareUnicodeCharacter{00DB}{\^U}%
\DeclareUnicodeCharacter{00DC}{\"U}%
\DeclareUnicodeCharacter{00DD}{\'Y}%
\DeclareUnicodeCharacter{00DE}{\TH}%
\DeclareUnicodeCharacter{00DF}{\ss}%
%
\DeclareUnicodeCharacter{00E0}{\`a}%
\DeclareUnicodeCharacter{00E1}{\'a}%
\DeclareUnicodeCharacter{00E2}{\^a}%
\DeclareUnicodeCharacter{00E3}{\~a}%
\DeclareUnicodeCharacter{00E4}{\"a}%
\DeclareUnicodeCharacter{00E5}{\aa}%
\DeclareUnicodeCharacter{00E6}{\ae}%
\DeclareUnicodeCharacter{00E7}{\cedilla{c}}%
\DeclareUnicodeCharacter{00E8}{\`e}%
\DeclareUnicodeCharacter{00E9}{\'e}%
\DeclareUnicodeCharacter{00EA}{\^e}%
\DeclareUnicodeCharacter{00EB}{\"e}%
\DeclareUnicodeCharacter{00EC}{\`{\dotless{i}}}%
\DeclareUnicodeCharacter{00ED}{\'{\dotless{i}}}%
\DeclareUnicodeCharacter{00EE}{\^{\dotless{i}}}%
\DeclareUnicodeCharacter{00EF}{\"{\dotless{i}}}%
%
\DeclareUnicodeCharacter{00F0}{\dh}%
\DeclareUnicodeCharacter{00F1}{\~n}%
\DeclareUnicodeCharacter{00F2}{\`o}%
\DeclareUnicodeCharacter{00F3}{\'o}%
\DeclareUnicodeCharacter{00F4}{\^o}%
\DeclareUnicodeCharacter{00F5}{\~o}%
\DeclareUnicodeCharacter{00F6}{\"o}%
\DeclareUnicodeCharacter{00F7}{\ensuremath\div}%
\DeclareUnicodeCharacter{00F8}{\o}%
\DeclareUnicodeCharacter{00F9}{\`u}%
\DeclareUnicodeCharacter{00FA}{\'u}%
\DeclareUnicodeCharacter{00FB}{\^u}%
\DeclareUnicodeCharacter{00FC}{\"u}%
\DeclareUnicodeCharacter{00FD}{\'y}%
\DeclareUnicodeCharacter{00FE}{\th}%
\DeclareUnicodeCharacter{00FF}{\"y}%
%
\DeclareUnicodeCharacter{0100}{\=A}%
\DeclareUnicodeCharacter{0101}{\=a}%
\DeclareUnicodeCharacter{0102}{\u{A}}%
\DeclareUnicodeCharacter{0103}{\u{a}}%
\DeclareUnicodeCharacter{0104}{\ogonek{A}}%
\DeclareUnicodeCharacter{0105}{\ogonek{a}}%
\DeclareUnicodeCharacter{0106}{\'C}%
\DeclareUnicodeCharacter{0107}{\'c}%
\DeclareUnicodeCharacter{0108}{\^C}%
\DeclareUnicodeCharacter{0109}{\^c}%
\DeclareUnicodeCharacter{010A}{\dotaccent{C}}%
\DeclareUnicodeCharacter{010B}{\dotaccent{c}}%
\DeclareUnicodeCharacter{010C}{\v{C}}%
\DeclareUnicodeCharacter{010D}{\v{c}}%
\DeclareUnicodeCharacter{010E}{\v{D}}%
\DeclareUnicodeCharacter{010F}{d'}%
%
\DeclareUnicodeCharacter{0110}{\DH}%
\DeclareUnicodeCharacter{0111}{\dh}%
\DeclareUnicodeCharacter{0112}{\=E}%
\DeclareUnicodeCharacter{0113}{\=e}%
\DeclareUnicodeCharacter{0114}{\u{E}}%
\DeclareUnicodeCharacter{0115}{\u{e}}%
\DeclareUnicodeCharacter{0116}{\dotaccent{E}}%
\DeclareUnicodeCharacter{0117}{\dotaccent{e}}%
\DeclareUnicodeCharacter{0118}{\ogonek{E}}%
\DeclareUnicodeCharacter{0119}{\ogonek{e}}%
\DeclareUnicodeCharacter{011A}{\v{E}}%
\DeclareUnicodeCharacter{011B}{\v{e}}%
\DeclareUnicodeCharacter{011C}{\^G}%
\DeclareUnicodeCharacter{011D}{\^g}%
\DeclareUnicodeCharacter{011E}{\u{G}}%
\DeclareUnicodeCharacter{011F}{\u{g}}%
%
\DeclareUnicodeCharacter{0120}{\dotaccent{G}}%
\DeclareUnicodeCharacter{0121}{\dotaccent{g}}%
\DeclareUnicodeCharacter{0122}{\cedilla{G}}%
\DeclareUnicodeCharacter{0123}{\cedilla{g}}%
\DeclareUnicodeCharacter{0124}{\^H}%
\DeclareUnicodeCharacter{0125}{\^h}%
\DeclareUnicodeCharacter{0126}{\missingcharmsg{H WITH STROKE}}%
\DeclareUnicodeCharacter{0127}{\missingcharmsg{h WITH STROKE}}%
\DeclareUnicodeCharacter{0128}{\~I}%
\DeclareUnicodeCharacter{0129}{\~{\dotless{i}}}%
\DeclareUnicodeCharacter{012A}{\=I}%
\DeclareUnicodeCharacter{012B}{\={\dotless{i}}}%
\DeclareUnicodeCharacter{012C}{\u{I}}%
\DeclareUnicodeCharacter{012D}{\u{\dotless{i}}}%
\DeclareUnicodeCharacter{012E}{\ogonek{I}}%
\DeclareUnicodeCharacter{012F}{\ogonek{i}}%
%
\DeclareUnicodeCharacter{0130}{\dotaccent{I}}%
\DeclareUnicodeCharacter{0131}{\dotless{i}}%
\DeclareUnicodeCharacter{0132}{IJ}%
\DeclareUnicodeCharacter{0133}{ij}%
\DeclareUnicodeCharacter{0134}{\^J}%
\DeclareUnicodeCharacter{0135}{\^{\dotless{j}}}%
\DeclareUnicodeCharacter{0136}{\cedilla{K}}%
\DeclareUnicodeCharacter{0137}{\cedilla{k}}%
\DeclareUnicodeCharacter{0138}{\ensuremath\kappa}%
\DeclareUnicodeCharacter{0139}{\'L}%
\DeclareUnicodeCharacter{013A}{\'l}%
\DeclareUnicodeCharacter{013B}{\cedilla{L}}%
\DeclareUnicodeCharacter{013C}{\cedilla{l}}%
\DeclareUnicodeCharacter{013D}{L'}% should kern
\DeclareUnicodeCharacter{013E}{l'}% should kern
\DeclareUnicodeCharacter{013F}{L\U{00B7}}%
%
\DeclareUnicodeCharacter{0140}{l\U{00B7}}%
\DeclareUnicodeCharacter{0141}{\L}%
\DeclareUnicodeCharacter{0142}{\l}%
\DeclareUnicodeCharacter{0143}{\'N}%
\DeclareUnicodeCharacter{0144}{\'n}%
\DeclareUnicodeCharacter{0145}{\cedilla{N}}%
\DeclareUnicodeCharacter{0146}{\cedilla{n}}%
\DeclareUnicodeCharacter{0147}{\v{N}}%
\DeclareUnicodeCharacter{0148}{\v{n}}%
\DeclareUnicodeCharacter{0149}{'n}%
\DeclareUnicodeCharacter{014A}{\missingcharmsg{ENG}}%
\DeclareUnicodeCharacter{014B}{\missingcharmsg{eng}}%
\DeclareUnicodeCharacter{014C}{\=O}%
\DeclareUnicodeCharacter{014D}{\=o}%
\DeclareUnicodeCharacter{014E}{\u{O}}%
\DeclareUnicodeCharacter{014F}{\u{o}}%
%
\DeclareUnicodeCharacter{0150}{\H{O}}%
\DeclareUnicodeCharacter{0151}{\H{o}}%
\DeclareUnicodeCharacter{0152}{\OE}%
\DeclareUnicodeCharacter{0153}{\oe}%
\DeclareUnicodeCharacter{0154}{\'R}%
\DeclareUnicodeCharacter{0155}{\'r}%
\DeclareUnicodeCharacter{0156}{\cedilla{R}}%
\DeclareUnicodeCharacter{0157}{\cedilla{r}}%
\DeclareUnicodeCharacter{0158}{\v{R}}%
\DeclareUnicodeCharacter{0159}{\v{r}}%
\DeclareUnicodeCharacter{015A}{\'S}%
\DeclareUnicodeCharacter{015B}{\'s}%
\DeclareUnicodeCharacter{015C}{\^S}%
\DeclareUnicodeCharacter{015D}{\^s}%
\DeclareUnicodeCharacter{015E}{\cedilla{S}}%
\DeclareUnicodeCharacter{015F}{\cedilla{s}}%
%
\DeclareUnicodeCharacter{0160}{\v{S}}%
\DeclareUnicodeCharacter{0161}{\v{s}}%
\DeclareUnicodeCharacter{0162}{\cedilla{T}}%
\DeclareUnicodeCharacter{0163}{\cedilla{t}}%
\DeclareUnicodeCharacter{0164}{\v{T}}%
\DeclareUnicodeCharacter{0165}{\v{t}}%
\DeclareUnicodeCharacter{0166}{\missingcharmsg{H WITH STROKE}}%
\DeclareUnicodeCharacter{0167}{\missingcharmsg{h WITH STROKE}}%
\DeclareUnicodeCharacter{0168}{\~U}%
\DeclareUnicodeCharacter{0169}{\~u}%
\DeclareUnicodeCharacter{016A}{\=U}%
\DeclareUnicodeCharacter{016B}{\=u}%
\DeclareUnicodeCharacter{016C}{\u{U}}%
\DeclareUnicodeCharacter{016D}{\u{u}}%
\DeclareUnicodeCharacter{016E}{\ringaccent{U}}%
\DeclareUnicodeCharacter{016F}{\ringaccent{u}}%
%
\DeclareUnicodeCharacter{0170}{\H{U}}%
\DeclareUnicodeCharacter{0171}{\H{u}}%
\DeclareUnicodeCharacter{0172}{\ogonek{U}}%
\DeclareUnicodeCharacter{0173}{\ogonek{u}}%
\DeclareUnicodeCharacter{0174}{\^W}%
\DeclareUnicodeCharacter{0175}{\^w}%
\DeclareUnicodeCharacter{0176}{\^Y}%
\DeclareUnicodeCharacter{0177}{\^y}%
\DeclareUnicodeCharacter{0178}{\"Y}%
\DeclareUnicodeCharacter{0179}{\'Z}%
\DeclareUnicodeCharacter{017A}{\'z}%
\DeclareUnicodeCharacter{017B}{\dotaccent{Z}}%
\DeclareUnicodeCharacter{017C}{\dotaccent{z}}%
\DeclareUnicodeCharacter{017D}{\v{Z}}%
\DeclareUnicodeCharacter{017E}{\v{z}}%
\DeclareUnicodeCharacter{017F}{\missingcharmsg{LONG S}}%
%
\DeclareUnicodeCharacter{01C4}{D\v{Z}}%
\DeclareUnicodeCharacter{01C5}{D\v{z}}%
\DeclareUnicodeCharacter{01C6}{d\v{z}}%
\DeclareUnicodeCharacter{01C7}{LJ}%
\DeclareUnicodeCharacter{01C8}{Lj}%
\DeclareUnicodeCharacter{01C9}{lj}%
\DeclareUnicodeCharacter{01CA}{NJ}%
\DeclareUnicodeCharacter{01CB}{Nj}%
\DeclareUnicodeCharacter{01CC}{nj}%
\DeclareUnicodeCharacter{01CD}{\v{A}}%
\DeclareUnicodeCharacter{01CE}{\v{a}}%
\DeclareUnicodeCharacter{01CF}{\v{I}}%
%
\DeclareUnicodeCharacter{01D0}{\v{\dotless{i}}}%
\DeclareUnicodeCharacter{01D1}{\v{O}}%
\DeclareUnicodeCharacter{01D2}{\v{o}}%
\DeclareUnicodeCharacter{01D3}{\v{U}}%
\DeclareUnicodeCharacter{01D4}{\v{u}}%
%
\DeclareUnicodeCharacter{01E2}{\={\AE}}%
\DeclareUnicodeCharacter{01E3}{\={\ae}}%
\DeclareUnicodeCharacter{01E6}{\v{G}}%
\DeclareUnicodeCharacter{01E7}{\v{g}}%
\DeclareUnicodeCharacter{01E8}{\v{K}}%
\DeclareUnicodeCharacter{01E9}{\v{k}}%
%
\DeclareUnicodeCharacter{01F0}{\v{\dotless{j}}}%
\DeclareUnicodeCharacter{01F1}{DZ}%
\DeclareUnicodeCharacter{01F2}{Dz}%
\DeclareUnicodeCharacter{01F3}{dz}%
\DeclareUnicodeCharacter{01F4}{\'G}%
\DeclareUnicodeCharacter{01F5}{\'g}%
\DeclareUnicodeCharacter{01F8}{\`N}%
\DeclareUnicodeCharacter{01F9}{\`n}%
\DeclareUnicodeCharacter{01FC}{\'{\AE}}%
\DeclareUnicodeCharacter{01FD}{\'{\ae}}%
\DeclareUnicodeCharacter{01FE}{\'{\O}}%
\DeclareUnicodeCharacter{01FF}{\'{\o}}%
%
\DeclareUnicodeCharacter{021E}{\v{H}}%
\DeclareUnicodeCharacter{021F}{\v{h}}%
%
\DeclareUnicodeCharacter{0226}{\dotaccent{A}}%
\DeclareUnicodeCharacter{0227}{\dotaccent{a}}%
\DeclareUnicodeCharacter{0228}{\cedilla{E}}%
\DeclareUnicodeCharacter{0229}{\cedilla{e}}%
\DeclareUnicodeCharacter{022E}{\dotaccent{O}}%
\DeclareUnicodeCharacter{022F}{\dotaccent{o}}%
%
\DeclareUnicodeCharacter{0232}{\=Y}%
\DeclareUnicodeCharacter{0233}{\=y}%
\DeclareUnicodeCharacter{0237}{\dotless{j}}%
%
\DeclareUnicodeCharacter{02BC}{'}%
%
\DeclareUnicodeCharacter{02DB}{\ogonek{ }}%
%
% Greek letters upper case
\DeclareUnicodeCharacter{0391}{{\it A}}%
\DeclareUnicodeCharacter{0392}{{\it B}}%
\DeclareUnicodeCharacter{0393}{\ensuremath{\mit\Gamma}}%
\DeclareUnicodeCharacter{0394}{\ensuremath{\mit\Delta}}%
\DeclareUnicodeCharacter{0395}{{\it E}}%
\DeclareUnicodeCharacter{0396}{{\it Z}}%
\DeclareUnicodeCharacter{0397}{{\it H}}%
\DeclareUnicodeCharacter{0398}{\ensuremath{\mit\Theta}}%
\DeclareUnicodeCharacter{0399}{{\it I}}%
\DeclareUnicodeCharacter{039A}{{\it K}}%
\DeclareUnicodeCharacter{039B}{\ensuremath{\mit\Lambda}}%
\DeclareUnicodeCharacter{039C}{{\it M}}%
\DeclareUnicodeCharacter{039D}{{\it N}}%
\DeclareUnicodeCharacter{039E}{\ensuremath{\mit\Xi}}%
\DeclareUnicodeCharacter{039F}{{\it O}}%
\DeclareUnicodeCharacter{03A0}{\ensuremath{\mit\Pi}}%
\DeclareUnicodeCharacter{03A1}{{\it P}}%
%\DeclareUnicodeCharacter{03A2}{} % none - corresponds to final sigma
\DeclareUnicodeCharacter{03A3}{\ensuremath{\mit\Sigma}}%
\DeclareUnicodeCharacter{03A4}{{\it T}}%
\DeclareUnicodeCharacter{03A5}{\ensuremath{\mit\Upsilon}}%
\DeclareUnicodeCharacter{03A6}{\ensuremath{\mit\Phi}}%
\DeclareUnicodeCharacter{03A7}{{\it X}}%
\DeclareUnicodeCharacter{03A8}{\ensuremath{\mit\Psi}}%
\DeclareUnicodeCharacter{03A9}{\ensuremath{\mit\Omega}}%
%
% Vowels with accents
\DeclareUnicodeCharacter{0390}{\ensuremath{\ddot{\acute\iota}}}%
\DeclareUnicodeCharacter{03AC}{\ensuremath{\acute\alpha}}%
\DeclareUnicodeCharacter{03AD}{\ensuremath{\acute\epsilon}}%
\DeclareUnicodeCharacter{03AE}{\ensuremath{\acute\eta}}%
\DeclareUnicodeCharacter{03AF}{\ensuremath{\acute\iota}}%
\DeclareUnicodeCharacter{03B0}{\ensuremath{\acute{\ddot\upsilon}}}%
%
% Standalone accent
\DeclareUnicodeCharacter{0384}{\ensuremath{\acute{\ }}}%
%
% Greek letters lower case
\DeclareUnicodeCharacter{03B1}{\ensuremath\alpha}%
\DeclareUnicodeCharacter{03B2}{\ensuremath\beta}%
\DeclareUnicodeCharacter{03B3}{\ensuremath\gamma}%
\DeclareUnicodeCharacter{03B4}{\ensuremath\delta}%
\DeclareUnicodeCharacter{03B5}{\ensuremath\epsilon}%
\DeclareUnicodeCharacter{03B6}{\ensuremath\zeta}%
\DeclareUnicodeCharacter{03B7}{\ensuremath\eta}%
\DeclareUnicodeCharacter{03B8}{\ensuremath\theta}%
\DeclareUnicodeCharacter{03B9}{\ensuremath\iota}%
\DeclareUnicodeCharacter{03BA}{\ensuremath\kappa}%
\DeclareUnicodeCharacter{03BB}{\ensuremath\lambda}%
\DeclareUnicodeCharacter{03BC}{\ensuremath\mu}%
\DeclareUnicodeCharacter{03BD}{\ensuremath\nu}%
\DeclareUnicodeCharacter{03BE}{\ensuremath\xi}%
\DeclareUnicodeCharacter{03BF}{{\it o}}% omicron
\DeclareUnicodeCharacter{03C0}{\ensuremath\pi}%
\DeclareUnicodeCharacter{03C1}{\ensuremath\rho}%
\DeclareUnicodeCharacter{03C2}{\ensuremath\varsigma}%
\DeclareUnicodeCharacter{03C3}{\ensuremath\sigma}%
\DeclareUnicodeCharacter{03C4}{\ensuremath\tau}%
\DeclareUnicodeCharacter{03C5}{\ensuremath\upsilon}%
\DeclareUnicodeCharacter{03C6}{\ensuremath\phi}%
\DeclareUnicodeCharacter{03C7}{\ensuremath\chi}%
\DeclareUnicodeCharacter{03C8}{\ensuremath\psi}%
\DeclareUnicodeCharacter{03C9}{\ensuremath\omega}%
%
% More Greek vowels with accents
\DeclareUnicodeCharacter{03CA}{\ensuremath{\ddot\iota}}%
\DeclareUnicodeCharacter{03CB}{\ensuremath{\ddot\upsilon}}%
\DeclareUnicodeCharacter{03CC}{\ensuremath{\acute o}}%
\DeclareUnicodeCharacter{03CD}{\ensuremath{\acute\upsilon}}%
\DeclareUnicodeCharacter{03CE}{\ensuremath{\acute\omega}}%
%
% Variant Greek letters
\DeclareUnicodeCharacter{03D1}{\ensuremath\vartheta}%
\DeclareUnicodeCharacter{03D6}{\ensuremath\varpi}%
\DeclareUnicodeCharacter{03F1}{\ensuremath\varrho}%
%
\DeclareUnicodeCharacter{1E02}{\dotaccent{B}}%
\DeclareUnicodeCharacter{1E03}{\dotaccent{b}}%
\DeclareUnicodeCharacter{1E04}{\udotaccent{B}}%
\DeclareUnicodeCharacter{1E05}{\udotaccent{b}}%
\DeclareUnicodeCharacter{1E06}{\ubaraccent{B}}%
\DeclareUnicodeCharacter{1E07}{\ubaraccent{b}}%
\DeclareUnicodeCharacter{1E0A}{\dotaccent{D}}%
\DeclareUnicodeCharacter{1E0B}{\dotaccent{d}}%
\DeclareUnicodeCharacter{1E0C}{\udotaccent{D}}%
\DeclareUnicodeCharacter{1E0D}{\udotaccent{d}}%
\DeclareUnicodeCharacter{1E0E}{\ubaraccent{D}}%
\DeclareUnicodeCharacter{1E0F}{\ubaraccent{d}}%
%
\DeclareUnicodeCharacter{1E1E}{\dotaccent{F}}%
\DeclareUnicodeCharacter{1E1F}{\dotaccent{f}}%
%
\DeclareUnicodeCharacter{1E20}{\=G}%
\DeclareUnicodeCharacter{1E21}{\=g}%
\DeclareUnicodeCharacter{1E22}{\dotaccent{H}}%
\DeclareUnicodeCharacter{1E23}{\dotaccent{h}}%
\DeclareUnicodeCharacter{1E24}{\udotaccent{H}}%
\DeclareUnicodeCharacter{1E25}{\udotaccent{h}}%
\DeclareUnicodeCharacter{1E26}{\"H}%
\DeclareUnicodeCharacter{1E27}{\"h}%
%
\DeclareUnicodeCharacter{1E30}{\'K}%
\DeclareUnicodeCharacter{1E31}{\'k}%
\DeclareUnicodeCharacter{1E32}{\udotaccent{K}}%
\DeclareUnicodeCharacter{1E33}{\udotaccent{k}}%
\DeclareUnicodeCharacter{1E34}{\ubaraccent{K}}%
\DeclareUnicodeCharacter{1E35}{\ubaraccent{k}}%
\DeclareUnicodeCharacter{1E36}{\udotaccent{L}}%
\DeclareUnicodeCharacter{1E37}{\udotaccent{l}}%
\DeclareUnicodeCharacter{1E3A}{\ubaraccent{L}}%
\DeclareUnicodeCharacter{1E3B}{\ubaraccent{l}}%
\DeclareUnicodeCharacter{1E3E}{\'M}%
\DeclareUnicodeCharacter{1E3F}{\'m}%
%
\DeclareUnicodeCharacter{1E40}{\dotaccent{M}}%
\DeclareUnicodeCharacter{1E41}{\dotaccent{m}}%
\DeclareUnicodeCharacter{1E42}{\udotaccent{M}}%
\DeclareUnicodeCharacter{1E43}{\udotaccent{m}}%
\DeclareUnicodeCharacter{1E44}{\dotaccent{N}}%
\DeclareUnicodeCharacter{1E45}{\dotaccent{n}}%
\DeclareUnicodeCharacter{1E46}{\udotaccent{N}}%
\DeclareUnicodeCharacter{1E47}{\udotaccent{n}}%
\DeclareUnicodeCharacter{1E48}{\ubaraccent{N}}%
\DeclareUnicodeCharacter{1E49}{\ubaraccent{n}}%
%
\DeclareUnicodeCharacter{1E54}{\'P}%
\DeclareUnicodeCharacter{1E55}{\'p}%
\DeclareUnicodeCharacter{1E56}{\dotaccent{P}}%
\DeclareUnicodeCharacter{1E57}{\dotaccent{p}}%
\DeclareUnicodeCharacter{1E58}{\dotaccent{R}}%
\DeclareUnicodeCharacter{1E59}{\dotaccent{r}}%
\DeclareUnicodeCharacter{1E5A}{\udotaccent{R}}%
\DeclareUnicodeCharacter{1E5B}{\udotaccent{r}}%
\DeclareUnicodeCharacter{1E5E}{\ubaraccent{R}}%
\DeclareUnicodeCharacter{1E5F}{\ubaraccent{r}}%
%
\DeclareUnicodeCharacter{1E60}{\dotaccent{S}}%
\DeclareUnicodeCharacter{1E61}{\dotaccent{s}}%
\DeclareUnicodeCharacter{1E62}{\udotaccent{S}}%
\DeclareUnicodeCharacter{1E63}{\udotaccent{s}}%
\DeclareUnicodeCharacter{1E6A}{\dotaccent{T}}%
\DeclareUnicodeCharacter{1E6B}{\dotaccent{t}}%
\DeclareUnicodeCharacter{1E6C}{\udotaccent{T}}%
\DeclareUnicodeCharacter{1E6D}{\udotaccent{t}}%
\DeclareUnicodeCharacter{1E6E}{\ubaraccent{T}}%
\DeclareUnicodeCharacter{1E6F}{\ubaraccent{t}}%
%
\DeclareUnicodeCharacter{1E7C}{\~V}%
\DeclareUnicodeCharacter{1E7D}{\~v}%
\DeclareUnicodeCharacter{1E7E}{\udotaccent{V}}%
\DeclareUnicodeCharacter{1E7F}{\udotaccent{v}}%
%
\DeclareUnicodeCharacter{1E80}{\`W}%
\DeclareUnicodeCharacter{1E81}{\`w}%
\DeclareUnicodeCharacter{1E82}{\'W}%
\DeclareUnicodeCharacter{1E83}{\'w}%
\DeclareUnicodeCharacter{1E84}{\"W}%
\DeclareUnicodeCharacter{1E85}{\"w}%
\DeclareUnicodeCharacter{1E86}{\dotaccent{W}}%
\DeclareUnicodeCharacter{1E87}{\dotaccent{w}}%
\DeclareUnicodeCharacter{1E88}{\udotaccent{W}}%
\DeclareUnicodeCharacter{1E89}{\udotaccent{w}}%
\DeclareUnicodeCharacter{1E8A}{\dotaccent{X}}%
\DeclareUnicodeCharacter{1E8B}{\dotaccent{x}}%
\DeclareUnicodeCharacter{1E8C}{\"X}%
\DeclareUnicodeCharacter{1E8D}{\"x}%
\DeclareUnicodeCharacter{1E8E}{\dotaccent{Y}}%
\DeclareUnicodeCharacter{1E8F}{\dotaccent{y}}%
%
\DeclareUnicodeCharacter{1E90}{\^Z}%
\DeclareUnicodeCharacter{1E91}{\^z}%
\DeclareUnicodeCharacter{1E92}{\udotaccent{Z}}%
\DeclareUnicodeCharacter{1E93}{\udotaccent{z}}%
\DeclareUnicodeCharacter{1E94}{\ubaraccent{Z}}%
\DeclareUnicodeCharacter{1E95}{\ubaraccent{z}}%
\DeclareUnicodeCharacter{1E96}{\ubaraccent{h}}%
\DeclareUnicodeCharacter{1E97}{\"t}%
\DeclareUnicodeCharacter{1E98}{\ringaccent{w}}%
\DeclareUnicodeCharacter{1E99}{\ringaccent{y}}%
%
\DeclareUnicodeCharacter{1EA0}{\udotaccent{A}}%
\DeclareUnicodeCharacter{1EA1}{\udotaccent{a}}%
%
\DeclareUnicodeCharacter{1EB8}{\udotaccent{E}}%
\DeclareUnicodeCharacter{1EB9}{\udotaccent{e}}%
\DeclareUnicodeCharacter{1EBC}{\~E}%
\DeclareUnicodeCharacter{1EBD}{\~e}%
%
\DeclareUnicodeCharacter{1ECA}{\udotaccent{I}}%
\DeclareUnicodeCharacter{1ECB}{\udotaccent{i}}%
\DeclareUnicodeCharacter{1ECC}{\udotaccent{O}}%
\DeclareUnicodeCharacter{1ECD}{\udotaccent{o}}%
%
\DeclareUnicodeCharacter{1EE4}{\udotaccent{U}}%
\DeclareUnicodeCharacter{1EE5}{\udotaccent{u}}%
%
\DeclareUnicodeCharacter{1EF2}{\`Y}%
\DeclareUnicodeCharacter{1EF3}{\`y}%
\DeclareUnicodeCharacter{1EF4}{\udotaccent{Y}}%
%
\DeclareUnicodeCharacter{1EF8}{\~Y}%
\DeclareUnicodeCharacter{1EF9}{\~y}%
%
% Exotic spaces
\DeclareUnicodeCharacter{2007}{\hphantom{0}}%
%
% Punctuation
\DeclareUnicodeCharacter{2013}{--}%
\DeclareUnicodeCharacter{2014}{---}%
\DeclareUnicodeCharacter{2018}{\quoteleft{}}%
\DeclareUnicodeCharacter{2019}{\quoteright{}}%
\DeclareUnicodeCharacter{201A}{\quotesinglbase{}}%
\DeclareUnicodeCharacter{201C}{\quotedblleft{}}%
\DeclareUnicodeCharacter{201D}{\quotedblright{}}%
\DeclareUnicodeCharacter{201E}{\quotedblbase{}}%
\DeclareUnicodeCharacter{2020}{\ensuremath\dagger}%
\DeclareUnicodeCharacter{2021}{\ensuremath\ddagger}%
\DeclareUnicodeCharacter{2022}{\bullet{}}%
\DeclareUnicodeCharacter{202F}{\thinspace}%
\DeclareUnicodeCharacter{2026}{\dots{}}%
\DeclareUnicodeCharacter{2039}{\guilsinglleft{}}%
\DeclareUnicodeCharacter{203A}{\guilsinglright{}}%
%
\DeclareUnicodeCharacter{20AC}{\euro{}}%
%
\DeclareUnicodeCharacter{2192}{\arrow}%
\DeclareUnicodeCharacter{21D2}{\result{}}%
%
% Mathematical symbols
\DeclareUnicodeCharacter{2200}{\ensuremath\forall}%
\DeclareUnicodeCharacter{2203}{\ensuremath\exists}%
\DeclareUnicodeCharacter{2208}{\ensuremath\in}%
\DeclareUnicodeCharacter{2212}{\minus{}}%
\DeclareUnicodeCharacter{2217}{\ast}%
\DeclareUnicodeCharacter{221E}{\ensuremath\infty}%
\DeclareUnicodeCharacter{2225}{\ensuremath\parallel}%
\DeclareUnicodeCharacter{2227}{\ensuremath\wedge}%
\DeclareUnicodeCharacter{2229}{\ensuremath\cap}%
\DeclareUnicodeCharacter{2261}{\equiv{}}%
\DeclareUnicodeCharacter{2264}{\ensuremath\leq}%
\DeclareUnicodeCharacter{2265}{\ensuremath\geq}%
\DeclareUnicodeCharacter{2282}{\ensuremath\subset}%
\DeclareUnicodeCharacter{2287}{\ensuremath\supseteq}%
%
\DeclareUnicodeCharacter{2016}{\ensuremath\Vert}%
\DeclareUnicodeCharacter{2032}{\ensuremath\prime}%
\DeclareUnicodeCharacter{210F}{\ensuremath\hbar}%
\DeclareUnicodeCharacter{2111}{\ensuremath\Im}%
\DeclareUnicodeCharacter{2113}{\ensuremath\ell}%
\DeclareUnicodeCharacter{2118}{\ensuremath\wp}%
\DeclareUnicodeCharacter{211C}{\ensuremath\Re}%
\DeclareUnicodeCharacter{2135}{\ensuremath\aleph}%
\DeclareUnicodeCharacter{2190}{\ensuremath\leftarrow}%
\DeclareUnicodeCharacter{2191}{\ensuremath\uparrow}%
\DeclareUnicodeCharacter{2193}{\ensuremath\downarrow}%
\DeclareUnicodeCharacter{2194}{\ensuremath\leftrightarrow}%
\DeclareUnicodeCharacter{2195}{\ensuremath\updownarrow}%
\DeclareUnicodeCharacter{2196}{\ensuremath\nwarrow}%
\DeclareUnicodeCharacter{2197}{\ensuremath\nearrow}%
\DeclareUnicodeCharacter{2198}{\ensuremath\searrow}%
\DeclareUnicodeCharacter{2199}{\ensuremath\swarrow}%
\DeclareUnicodeCharacter{21A6}{\ensuremath\mapsto}%
\DeclareUnicodeCharacter{21A9}{\ensuremath\hookleftarrow}%
\DeclareUnicodeCharacter{21AA}{\ensuremath\hookrightarrow}%
\DeclareUnicodeCharacter{21BC}{\ensuremath\leftharpoonup}%
\DeclareUnicodeCharacter{21BD}{\ensuremath\leftharpoondown}%
\DeclareUnicodeCharacter{21C0}{\ensuremath\rightharpoonup}%
\DeclareUnicodeCharacter{21C1}{\ensuremath\rightharpoondown}%
\DeclareUnicodeCharacter{21CC}{\ensuremath\rightleftharpoons}%
\DeclareUnicodeCharacter{21D0}{\ensuremath\Leftarrow}%
\DeclareUnicodeCharacter{21D1}{\ensuremath\Uparrow}%
\DeclareUnicodeCharacter{21D3}{\ensuremath\Downarrow}%
\DeclareUnicodeCharacter{21D4}{\ensuremath\Leftrightarrow}%
\DeclareUnicodeCharacter{21D5}{\ensuremath\Updownarrow}%
\DeclareUnicodeCharacter{2202}{\ensuremath\partial}%
\DeclareUnicodeCharacter{2205}{\ensuremath\emptyset}%
\DeclareUnicodeCharacter{2207}{\ensuremath\nabla}%
\DeclareUnicodeCharacter{2209}{\ensuremath\notin}%
\DeclareUnicodeCharacter{220B}{\ensuremath\owns}%
\DeclareUnicodeCharacter{220F}{\ensuremath\prod}%
\DeclareUnicodeCharacter{2210}{\ensuremath\coprod}%
\DeclareUnicodeCharacter{2211}{\ensuremath\sum}%
\DeclareUnicodeCharacter{2213}{\ensuremath\mp}%
\DeclareUnicodeCharacter{2218}{\ensuremath\circ}%
\DeclareUnicodeCharacter{221A}{\ensuremath\surd}%
\DeclareUnicodeCharacter{221D}{\ensuremath\propto}%
\DeclareUnicodeCharacter{2220}{\ensuremath\angle}%
\DeclareUnicodeCharacter{2223}{\ensuremath\mid}%
\DeclareUnicodeCharacter{2228}{\ensuremath\vee}%
\DeclareUnicodeCharacter{222A}{\ensuremath\cup}%
\DeclareUnicodeCharacter{222B}{\ensuremath\smallint}%
\DeclareUnicodeCharacter{222E}{\ensuremath\oint}%
\DeclareUnicodeCharacter{223C}{\ensuremath\sim}%
\DeclareUnicodeCharacter{2240}{\ensuremath\wr}%
\DeclareUnicodeCharacter{2243}{\ensuremath\simeq}%
\DeclareUnicodeCharacter{2245}{\ensuremath\cong}%
\DeclareUnicodeCharacter{2248}{\ensuremath\approx}%
\DeclareUnicodeCharacter{224D}{\ensuremath\asymp}%
\DeclareUnicodeCharacter{2250}{\ensuremath\doteq}%
\DeclareUnicodeCharacter{2260}{\ensuremath\neq}%
\DeclareUnicodeCharacter{226A}{\ensuremath\ll}%
\DeclareUnicodeCharacter{226B}{\ensuremath\gg}%
\DeclareUnicodeCharacter{227A}{\ensuremath\prec}%
\DeclareUnicodeCharacter{227B}{\ensuremath\succ}%
\DeclareUnicodeCharacter{2283}{\ensuremath\supset}%
\DeclareUnicodeCharacter{2286}{\ensuremath\subseteq}%
\DeclareUnicodeCharacter{228E}{\ensuremath\uplus}%
\DeclareUnicodeCharacter{2291}{\ensuremath\sqsubseteq}%
\DeclareUnicodeCharacter{2292}{\ensuremath\sqsupseteq}%
\DeclareUnicodeCharacter{2293}{\ensuremath\sqcap}%
\DeclareUnicodeCharacter{2294}{\ensuremath\sqcup}%
\DeclareUnicodeCharacter{2295}{\ensuremath\oplus}%
\DeclareUnicodeCharacter{2296}{\ensuremath\ominus}%
\DeclareUnicodeCharacter{2297}{\ensuremath\otimes}%
\DeclareUnicodeCharacter{2298}{\ensuremath\oslash}%
\DeclareUnicodeCharacter{2299}{\ensuremath\odot}%
\DeclareUnicodeCharacter{22A2}{\ensuremath\vdash}%
\DeclareUnicodeCharacter{22A3}{\ensuremath\dashv}%
\DeclareUnicodeCharacter{22A4}{\ensuremath\ptextop}%
\DeclareUnicodeCharacter{22A5}{\ensuremath\bot}%
\DeclareUnicodeCharacter{22A8}{\ensuremath\models}%
\DeclareUnicodeCharacter{22C0}{\ensuremath\bigwedge}%
\DeclareUnicodeCharacter{22C1}{\ensuremath\bigvee}%
\DeclareUnicodeCharacter{22C2}{\ensuremath\bigcap}%
\DeclareUnicodeCharacter{22C3}{\ensuremath\bigcup}%
\DeclareUnicodeCharacter{22C4}{\ensuremath\diamond}%
\DeclareUnicodeCharacter{22C5}{\ensuremath\cdot}%
\DeclareUnicodeCharacter{22C6}{\ensuremath\star}%
\DeclareUnicodeCharacter{22C8}{\ensuremath\bowtie}%
\DeclareUnicodeCharacter{2308}{\ensuremath\lceil}%
\DeclareUnicodeCharacter{2309}{\ensuremath\rceil}%
\DeclareUnicodeCharacter{230A}{\ensuremath\lfloor}%
\DeclareUnicodeCharacter{230B}{\ensuremath\rfloor}%
\DeclareUnicodeCharacter{2322}{\ensuremath\frown}%
\DeclareUnicodeCharacter{2323}{\ensuremath\smile}%
%
\DeclareUnicodeCharacter{25B3}{\ensuremath\triangle}%
\DeclareUnicodeCharacter{25B7}{\ensuremath\triangleright}%
\DeclareUnicodeCharacter{25BD}{\ensuremath\bigtriangledown}%
\DeclareUnicodeCharacter{25C1}{\ensuremath\triangleleft}%
\DeclareUnicodeCharacter{25C7}{\ensuremath\diamond}%
\DeclareUnicodeCharacter{2660}{\ensuremath\spadesuit}%
\DeclareUnicodeCharacter{2661}{\ensuremath\heartsuit}%
\DeclareUnicodeCharacter{2662}{\ensuremath\diamondsuit}%
\DeclareUnicodeCharacter{2663}{\ensuremath\clubsuit}%
\DeclareUnicodeCharacter{266D}{\ensuremath\flat}%
\DeclareUnicodeCharacter{266E}{\ensuremath\natural}%
\DeclareUnicodeCharacter{266F}{\ensuremath\sharp}%
\DeclareUnicodeCharacter{26AA}{\ensuremath\bigcirc}%
\DeclareUnicodeCharacter{27B9}{\ensuremath\rangle}%
\DeclareUnicodeCharacter{27C2}{\ensuremath\perp}%
\DeclareUnicodeCharacter{27E8}{\ensuremath\langle}%
\DeclareUnicodeCharacter{27F5}{\ensuremath\longleftarrow}%
\DeclareUnicodeCharacter{27F6}{\ensuremath\longrightarrow}%
\DeclareUnicodeCharacter{27F7}{\ensuremath\longleftrightarrow}%
\DeclareUnicodeCharacter{27FC}{\ensuremath\longmapsto}%
\DeclareUnicodeCharacter{29F5}{\ensuremath\setminus}%
\DeclareUnicodeCharacter{2A00}{\ensuremath\bigodot}%
\DeclareUnicodeCharacter{2A01}{\ensuremath\bigoplus}%
\DeclareUnicodeCharacter{2A02}{\ensuremath\bigotimes}%
\DeclareUnicodeCharacter{2A04}{\ensuremath\biguplus}%
\DeclareUnicodeCharacter{2A06}{\ensuremath\bigsqcup}%
\DeclareUnicodeCharacter{2A3F}{\ensuremath\amalg}%
\DeclareUnicodeCharacter{2AAF}{\ensuremath\preceq}%
\DeclareUnicodeCharacter{2AB0}{\ensuremath\succeq}%
%
\global\mathchardef\checkmark="1370% actually the square root sign
\DeclareUnicodeCharacter{2713}{\ensuremath\checkmark}%
}% end of \unicodechardefs
% UTF-8 byte sequence (pdfTeX) definitions (replacing and @U command)
% It makes the setting that replace UTF-8 byte sequence.
\def\utfeightchardefs{%
\let\DeclareUnicodeCharacter\DeclareUnicodeCharacterUTFviii
\unicodechardefs
}
% Whether the active definitions of non-ASCII characters expand to
% non-active tokens with the same character code. This is used to
% write characters literally, instead of using active definitions for
% printing the correct glyphs.
\newif\ifpassthroughchars
\passthroughcharsfalse
% For native Unicode handling (XeTeX and LuaTeX),
% provide a definition macro to replace/pass-through a Unicode character
%
\def\DeclareUnicodeCharacterNative#1#2{%
\ifnum"#1>"7F % only make non-ASCII chars active
\catcode"#1=\active
\def\dodeclareunicodecharacternative##1##2##3{%
\begingroup
\uccode`\~="##2\relax
\uppercase{\gdef~}{%
\ifpassthroughchars
##1%
\else
##3%
\fi
}
\endgroup
}
\begingroup
\uccode`\.="#1\relax
\uppercase{\def\UTFNativeTmp{.}}%
\expandafter\dodeclareunicodecharacternative\UTFNativeTmp{#1}{#2}%
\endgroup
\fi
}
% Native Unicode handling (XeTeX and LuaTeX) character replacing definition.
% It activates the setting that replaces Unicode characters.
\def\nativeunicodechardefs{%
\let\DeclareUnicodeCharacter\DeclareUnicodeCharacterNative
\unicodechardefs
}
% For native Unicode handling (XeTeX and LuaTeX),
% make the character token expand
% to the sequences given in \unicodechardefs for printing.
\def\DeclareUnicodeCharacterNativeAtU#1#2{%
\def\UTFAtUTmp{#2}
\expandafter\globallet\csname uni:#1\endcsname \UTFAtUTmp
}
% @U command definitions for native Unicode handling (XeTeX and LuaTeX).
\def\nativeunicodechardefsatu{%
\let\DeclareUnicodeCharacter\DeclareUnicodeCharacterNativeAtU
\unicodechardefs
}
% US-ASCII character definitions.
\def\asciichardefs{% nothing need be done
\relax
}
% Define all Unicode characters we know about
\iftxinativeunicodecapable
\nativeunicodechardefsatu
\else
\utfeightchardefs
\fi
\message{formatting,}
\newdimen\defaultparindent \defaultparindent = 15pt
\chapheadingskip = 15pt plus 4pt minus 2pt
\secheadingskip = 12pt plus 3pt minus 2pt
\subsecheadingskip = 9pt plus 2pt minus 2pt
% Prevent underfull vbox error messages.
\vbadness = 10000
% Don't be very finicky about underfull hboxes, either.
\hbadness = 6666
% Following George Bush, get rid of widows and orphans.
\widowpenalty=10000
\clubpenalty=10000
% Use TeX 3.0's \emergencystretch to help line breaking, but if we're
% using an old version of TeX, don't do anything. We want the amount of
% stretch added to depend on the line length, hence the dependence on
% \hsize. We call this whenever the paper size is set.
%
\def\setemergencystretch{%
\ifx\emergencystretch\thisisundefined
% Allow us to assign to \emergencystretch anyway.
\def\emergencystretch{\dimen0}%
\else
\emergencystretch = .15\hsize
\fi
}
% Parameters in order: 1) textheight; 2) textwidth;
% 3) voffset; 4) hoffset; 5) binding offset; 6) topskip;
% 7) physical page height; 8) physical page width.
%
% We also call \setleading{\textleading}, so the caller should define
% \textleading. The caller should also set \parskip.
%
\def\internalpagesizes#1#2#3#4#5#6#7#8{%
\voffset = #3\relax
\topskip = #6\relax
\splittopskip = \topskip
%
\vsize = #1\relax
\advance\vsize by \topskip
\txipageheight = \vsize
%
\hsize = #2\relax
\txipagewidth = \hsize
%
\normaloffset = #4\relax
\bindingoffset = #5\relax
%
\ifpdf
\pdfpageheight #7\relax
\pdfpagewidth #8\relax
% if we don't reset these, they will remain at "1 true in" of
% whatever layout pdftex was dumped with.
\pdfhorigin = 1 true in
\pdfvorigin = 1 true in
\else
\ifx\XeTeXrevision\thisisundefined
\special{papersize=#8,#7}%
\else
\pdfpageheight #7\relax
\pdfpagewidth #8\relax
% XeTeX does not have \pdfhorigin and \pdfvorigin.
\fi
\fi
%
\setleading{\textleading}
%
\parindent = \defaultparindent
\setemergencystretch
}
% @letterpaper (the default).
\def\letterpaper{{\globaldefs = 1
\parskip = 3pt plus 2pt minus 1pt
\textleading = 13.2pt
%
% If page is nothing but text, make it come out even.
\internalpagesizes{607.2pt}{6in}% that's 46 lines
{\voffset}{.25in}%
{\bindingoffset}{36pt}%
{11in}{8.5in}%
}}
% Use @smallbook to reset parameters for 7x9.25 trim size.
\def\smallbook{{\globaldefs = 1
\parskip = 2pt plus 1pt
\textleading = 12pt
%
\internalpagesizes{7.5in}{5in}%
{-.2in}{0in}%
{\bindingoffset}{16pt}%
{9.25in}{7in}%
%
\lispnarrowing = 0.3in
\tolerance = 700
\contentsrightmargin = 0pt
\defbodyindent = .5cm
}}
% Use @afourpaper to print on European A4 paper.
\def\afourpaper{{\globaldefs = 1
\parskip = 3pt plus 2pt minus 1pt
\textleading = 13.2pt
%
% Double-side printing via postscript on Laserjet 4050
% prints double-sided nicely when \bindingoffset=10mm and \hoffset=-6mm.
% To change the settings for a different printer or situation, adjust
% \normaloffset until the front-side and back-side texts align. Then
% do the same for \bindingoffset. You can set these for testing in
% your texinfo source file like this:
% @tex
% \global\normaloffset = -6mm
% \global\bindingoffset = 10mm
% @end tex
\internalpagesizes{673.2pt}{160mm}% that's 51 lines
{\voffset}{\hoffset}%
{\bindingoffset}{44pt}%
{297mm}{210mm}%
%
\tolerance = 700
\contentsrightmargin = 0pt
\defbodyindent = 5mm
}}
% Use @afivepaper to print on European A5 paper.
% From romildo@urano.iceb.ufop.br, 2 July 2000.
% He also recommends making @example and @lisp be small.
\def\afivepaper{{\globaldefs = 1
\parskip = 2pt plus 1pt minus 0.1pt
\textleading = 12.5pt
%
\internalpagesizes{160mm}{120mm}%
{\voffset}{-11.4mm}%
{\bindingoffset}{8pt}%
{210mm}{148mm}%
%
\lispnarrowing = 0.2in
\tolerance = 800
\contentsrightmargin = 0pt
\defbodyindent = 2mm
\tableindent = 12mm
}}
% A specific text layout, 24x15cm overall, intended for A4 paper.
\def\afourlatex{{\globaldefs = 1
\afourpaper
\internalpagesizes{237mm}{150mm}%
{\voffset}{4.6mm}%
{\bindingoffset}{7mm}%
{297mm}{210mm}%
%
% Must explicitly reset to 0 because we call \afourpaper.
\globaldefs = 0
}}
% Use @afourwide to print on A4 paper in landscape format.
\def\afourwide{{\globaldefs = 1
\afourpaper
\internalpagesizes{241mm}{165mm}%
{\voffset}{-2.95mm}%
{\bindingoffset}{7mm}%
{297mm}{210mm}%
\globaldefs = 0
}}
\def\bsixpaper{{\globaldefs = 1
\afourpaper
\internalpagesizes{140mm}{100mm}%
{-6.35mm}{-12.7mm}%
{\bindingoffset}{14pt}%
{176mm}{125mm}%
\let\SETdispenvsize=\smallword
\lispnarrowing = 0.2in
\globaldefs = 0
}}
% @pagesizes TEXTHEIGHT[,TEXTWIDTH]
% Perhaps we should allow setting the margins, \topskip, \parskip,
% and/or leading, also. Or perhaps we should compute them somehow.
%
\parseargdef\pagesizes{\pagesizesyyy #1,,\finish}
\def\pagesizesyyy#1,#2,#3\finish{{%
\setbox0 = \hbox{\ignorespaces #2}\ifdim\wd0 > 0pt \hsize=#2\relax \fi
\globaldefs = 1
%
\parskip = 3pt plus 2pt minus 1pt
\setleading{\textleading}%
%
\dimen0 = #1\relax
\advance\dimen0 by 2.5in % default 1in margin above heading line
% and 1.5in to include heading, footing and
% bottom margin
%
\dimen2 = \hsize
\advance\dimen2 by 2in % default to 1 inch margin on each side
%
\internalpagesizes{#1}{\hsize}%
{\voffset}{\normaloffset}%
{\bindingoffset}{44pt}%
{\dimen0}{\dimen2}%
}}
% Set default to letter.
%
\letterpaper
% Default value of \hfuzz, for suppressing warnings about overfull hboxes.
\hfuzz = 1pt
\message{microtype,}
% protrusion, from Thanh's protcode.tex.
\def\mtsetprotcode#1{%
\rpcode#1`\!=200 \rpcode#1`\,=700 \rpcode#1`\-=700 \rpcode#1`\.=700
\rpcode#1`\;=500 \rpcode#1`\:=500 \rpcode#1`\?=200
\rpcode#1`\'=700
\rpcode#1 34=500 % ''
\rpcode#1 123=300 % --
\rpcode#1 124=200 % ---
\rpcode#1`\)=50 \rpcode#1`\A=50 \rpcode#1`\F=50 \rpcode#1`\K=50
\rpcode#1`\L=50 \rpcode#1`\T=50 \rpcode#1`\V=50 \rpcode#1`\W=50
\rpcode#1`\X=50 \rpcode#1`\Y=50 \rpcode#1`\k=50 \rpcode#1`\r=50
\rpcode#1`\t=50 \rpcode#1`\v=50 \rpcode#1`\w=50 \rpcode#1`\x=50
\rpcode#1`\y=50
%
\lpcode#1`\`=700
\lpcode#1 92=500 % ``
\lpcode#1`\(=50 \lpcode#1`\A=50 \lpcode#1`\J=50 \lpcode#1`\T=50
\lpcode#1`\V=50 \lpcode#1`\W=50 \lpcode#1`\X=50 \lpcode#1`\Y=50
\lpcode#1`\v=50 \lpcode#1`\w=50 \lpcode#1`\x=50 \lpcode#1`\y=0
%
\mtadjustprotcode#1\relax
}
\newcount\countC
\def\mtadjustprotcode#1{%
\countC=0
\loop
\ifcase\lpcode#1\countC\else
\mtadjustcp\lpcode#1\countC
\fi
\ifcase\rpcode#1\countC\else
\mtadjustcp\rpcode#1\countC
\fi
\advance\countC 1
\ifnum\countC < 256 \repeat
}
\newcount\countB
\def\mtadjustcp#1#2#3{%
\setbox\boxA=\hbox{%
\ifx#2\font\else#2\fi
\char#3}%
\countB=\wd\boxA
\multiply\countB #1#2#3\relax
\divide\countB \fontdimen6 #2\relax
#1#2#3=\countB\relax
}
\ifx\XeTeXrevision\thisisundefined
\ifx\luatexversion\thisisundefined
\ifpdf % pdfTeX
\mtsetprotcode\textrm
\def\mtfontexpand#1{\pdffontexpand#1 20 20 1 autoexpand\relax}
\else % TeX
\def\mtfontexpand#1{}
\fi
\else % LuaTeX
\mtsetprotcode\textrm
\def\mtfontexpand#1{\expandglyphsinfont#1 20 20 1\relax}
\fi
\else % XeTeX
\mtsetprotcode\textrm
\def\mtfontexpand#1{}
\fi
\newif\ifmicrotype
\def\microtypeON{%
\microtypetrue
%
\ifx\XeTeXrevision\thisisundefined
\ifx\luatexversion\thisisundefined
\ifpdf % pdfTeX
\pdfadjustspacing=2
\pdfprotrudechars=2
\fi
\else % LuaTeX
\adjustspacing=2
\protrudechars=2
\fi
\else % XeTeX
\XeTeXprotrudechars=2
\fi
%
\mtfontexpand\textrm
\mtfontexpand\textsl
\mtfontexpand\textbf
}
\def\microtypeOFF{%
\microtypefalse
%
\ifx\XeTeXrevision\thisisundefined
\ifx\luatexversion\thisisundefined
\ifpdf % pdfTeX
\pdfadjustspacing=0
\pdfprotrudechars=0
\fi
\else % LuaTeX
\adjustspacing=0
\protrudechars=0
\fi
\else % XeTeX
\XeTeXprotrudechars=0
\fi
}
\microtypeOFF
\parseargdef\microtype{%
\def\txiarg{#1}%
\ifx\txiarg\onword
\microtypeON
\else\ifx\txiarg\offword
\microtypeOFF
\else
\errhelp = \EMsimple
\errmessage{Unknown @microtype option `\txiarg', must be on|off}%
\fi\fi
}
\message{and turning on texinfo input format.}
% Make UTF-8 the default encoding.
\documentencodingzzz{UTF-8}
\def^^L{\par} % remove \outer, so ^L can appear in an @comment
\catcode`\^^K = 10 % treat vertical tab as whitespace
% DEL is a comment character, in case @c does not suffice.
\catcode`\^^? = 14
% Define macros to output various characters with catcode for normal text.
\catcode`\"=\other \def\normaldoublequote{"}
\catcode`\$=\other \def\normaldollar{$}%$ font-lock fix
\catcode`\+=\other \def\normalplus{+}
\catcode`\<=\other \def\normalless{<}
\catcode`\>=\other \def\normalgreater{>}
\catcode`\^=\other \def\normalcaret{^}
\catcode`\_=\other \def\normalunderscore{_}
\catcode`\|=\other \def\normalverticalbar{|}
\catcode`\~=\other \def\normaltilde{~}
% Set catcodes for Texinfo file
% Active characters for printing the wanted glyph.
% Most of these we simply print from the \tt font, but for some, we can
% use math or other variants that look better in normal text.
%
\catcode`\"=\active
\def\activedoublequote{{\tt\char34}}
\let"=\activedoublequote
\catcode`\~=\active \def\activetilde{{\tt\char126}} \let~ = \activetilde
\chardef\hatchar=`\^
\catcode`\^=\active \def\activehat{{\tt \hatchar}} \let^ = \activehat
\catcode`\_=\active
\def_{\ifusingtt\normalunderscore\_}
\def\_{\leavevmode \kern.07em \vbox{\hrule width.3em height.1ex}\kern .07em }
\let\realunder=_
\catcode`\|=\active \def|{{\tt\char124}}
\chardef \less=`\<
\catcode`\<=\active \def\activeless{{\tt \less}}\let< = \activeless
\chardef \gtr=`\>
\catcode`\>=\active \def\activegtr{{\tt \gtr}}\let> = \activegtr
\catcode`\+=\active \def+{{\tt \char 43}}
\catcode`\$=\active \def${\ifusingit{{\sl\$}}\normaldollar}%$ font-lock fix
\catcode`\-=\active \let-=\normaldash
% used for headline/footline in the output routine, in case the page
% breaks in the middle of an @tex block.
\def\texinfochars{%
\let< = \activeless
\let> = \activegtr
\let~ = \activetilde
\let^ = \activehat
\setregularquotes
\let\b = \strong
\let\i = \smartitalic
% in principle, all other definitions in \tex have to be undone too.
}
% Used sometimes to turn off (effectively) the active characters even after
% parsing them.
\def\turnoffactive{%
\passthroughcharstrue
\let-=\normaldash
\let"=\normaldoublequote
\let$=\normaldollar %$ font-lock fix
\let+=\normalplus
\let<=\normalless
\let>=\normalgreater
\let^=\normalcaret
\let_=\normalunderscore
\let|=\normalverticalbar
\let~=\normaltilde
\otherbackslash
\setregularquotes
\unsepspaces
}
% If a .fmt file is being used, characters that might appear in a file
% name cannot be active until we have parsed the command line.
% So turn them off again, and have \loadconf turn them back on.
\catcode`+=\other \catcode`\_=\other
% \backslashcurfont outputs one backslash character in current font,
% as in \char`\\.
\global\chardef\backslashcurfont=`\\
% Print a typewriter backslash. For math mode, we can't simply use
% \backslashcurfont: the story here is that in math mode, the \char
% of \backslashcurfont ends up printing the roman \ from the math symbol
% font (because \char in math mode uses the \mathcode, and plain.tex
% sets \mathcode`\\="026E). Hence we use an explicit \mathchar,
% which is the decimal equivalent of "715c (class 7, e.g., use \fam;
% ignored family value; char position "5C). We can't use " for the
% usual hex value because it has already been made active.
\def\ttbackslash{{\tt \ifmmode \mathchar29020 \else \backslashcurfont \fi}}
\let\backslashchar = \ttbackslash % \backslashchar{} is for user documents.
% These are made active for url-breaking, so need
% active definitions as the normal characters.
\def\normaldot{.}
\def\normalquest{?}
\def\normalslash{/}
% \newlinesloadsconf - call \loadconf as soon as possible in the
% file, e.g. at the first newline.
%
{\catcode`\^=7
\catcode`\^^M=13
\gdef\newlineloadsconf{%
\catcode`\^^M=13 %
\newlineloadsconfzz%
}
\gdef\newlineloadsconfzz#1^^M{%
\def\c{\loadconf\c}%
% Definition for the first newline read in the file
\def ^^M{\loadconf}%
% In case the first line has a whole-line or environment command on it
\let\originalparsearg\parsearg%
\def\parsearg{\loadconf\originalparsearg}%
%
% \startenvironment is in the expansion of commands defined with \envdef
\let\originalstartenvironment\startenvironment%
\def\startenvironment{\loadconf\startenvironment}%
}}
% Emergency active definition of newline, in case an active newline token
% appears by mistake.
{\catcode`\^=7 \catcode13=13%
\gdef\enableemergencynewline{%
\gdef^^M{%
\par%
%\par%
}}}
% \loadconf gets called at the beginning of every Texinfo file.
% If texinfo.cnf is present on the system, read it. Useful for site-wide
% @afourpaper, etc. Not opening texinfo.cnf directly in texinfo.tex
% makes it possible to make a format file for Texinfo.
%
\gdef\loadconf{%
\relax % Terminate the filename if running as "tex '&texinfo' FILE.texi".
%
% Turn off the definitions that trigger \loadconf
\everyjobreset
\catcode13=5 % regular end of line
\enableemergencynewline
\let\c=\comment
\let\parsearg\originalparsearg
\let\startenvironment\originalstartenvironment
%
% Also turn back on active characters that might appear in the input
% file name, in case not using a pre-dumped format.
\catcode`+=\active
\catcode`\_=\active
%
\openin 1 texinfo.cnf
\ifeof 1 \else \input texinfo.cnf \fi
\closein 1
}
% Redefine some control sequences to be controlled by the \ifdummies
% and \ifindexnofonts switches. Do this at the end so that the control
% sequences are all defined.
\definedummies
\catcode`\@=0
% \realbackslash is an actual character `\' with catcode other.
{\catcode`\\=\other @gdef@realbackslash{\}}
% In Texinfo, backslash is an active character; it prints the backslash
% in fixed width font.
\catcode`\\=\active % @ for escape char from now on.
@let\ = @ttbackslash
% If in a .fmt file, print the version number.
% \eatinput stops the `\input texinfo' from showing up.
% After that, `\' should revert to printing a backslash.
% Turn on active characters that we couldn't do earlier because
% they might have appeared in the input file name.
%
@everyjob{@message{[Texinfo version @texinfoversion]}%
@global@let\ = @eatinput
@catcode`+=@active @catcode`@_=@active}
{@catcode`@^=7 @catcode`@^^M=13%
@gdef@eatinput input texinfo#1^^M{@loadconf}}
@def@everyjobreset{@ifx\@eatinput @let\ = @ttbackslash @fi}
% \otherbackslash defines an active \ to be a literal `\' character with
% catcode other.
@gdef@otherbackslash{@let\=@realbackslash}
% Same as @turnoffactive except outputs \ as {\tt\char`\\} instead of
% the literal character `\'.
%
{@catcode`- = @active
@gdef@normalturnoffactive{%
@turnoffactive
@let\=@ttbackslash
}
}
% Say @foo, not \foo, in error messages.
@escapechar = `@@
% These look ok in all fonts, so just make them not special.
% @hashchar{} gets its own user-level command, because of #line.
@catcode`@& = @other @def@normalamp{&}
@catcode`@# = @other @def@normalhash{#}
@catcode`@% = @other @def@normalpercent{%}
@let @hashchar = @normalhash
@c Finally, make ` and ' active, so that txicodequoteundirected and
@c txicodequotebacktick work right in, e.g., @w{@code{`foo'}}. If we
@c don't make ` and ' active, @code will not get them as active chars.
@c Do this last of all since we use ` in the previous @catcode assignments.
@catcode`@'=@active
@catcode`@`=@active
@c Local variables:
@c eval: (add-hook 'before-save-hook 'time-stamp nil t)
@c time-stamp-pattern: "texinfoversion{%Y-%02m-%02d.%02H}"
@c page-delimiter: "^\\\\message"
@c End:
@newlineloadsconf
mdk-1.3.1/doc/mdk_ack.texi 0000644 0001750 0001750 00000005367 12636571173 011027 @c -*-texinfo-*-
@c This is part of the GNU MDK Reference Manual.
@c Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2013, 2014, 2015
@c Free Software Foundation, Inc.
@c See the file mdk.texi for copying conditions.
@node Acknowledgments, Installing MDK, Introduction, Top
@comment node-name, next, previous, up
@unnumbered Acknowledgements
Many people have further contributed to @sc{mdk} by reporting problems,
suggesting various improvements, or submitting actual code. Here is a
list of these people. Please, help me keep it complete and exempt of
errors.
@itemize @bullet
@item Philip Ellis King
provided MIXAL test programs pinpointing bugs in the first @sc{mdk}
release, and useful discussions as well. Philip has also contributed
with the Emacs port of @code{mixvm} and influenced the @code{gmixvm} GUI
design with insightful comments and prototypes.
@item Aleix Conchillo
has been following @sc{mdk}'s development for many years, indefatigably
chasing and fixing bugs, and suggesting many improvements. He's also the
original author of the Fink and Macports ports.
@item Pieter E J Pareit
is the author of the Emacs MIXAL mode, and has also contributed many
bug fixes.
@item Michael Scholz
is the author of the German translation of @sc{mdk}'s user interface.
@item Sergey Poznyakoff
provided patches to mixlib/mix_scanner.l improving MIXAL compliance.
@item Sergey Litvin
implemented the instructions @code{SLB}, @code{SRB}, @code{JAE},
@code{JAO}, @code{JXE}, and @code{JXO} from volume 2 of TAOCP.
@item Francesc Xavier Noria
kindly and thoroughly reviewed the @sc{mdk} documentation, providing
insightful advice.
@item Eric S. Raymond
contributed the documentation file @file{MIX.DOC} and the samples
@file{elevator.mixal} and @file{mistery.mixal} from his MIXAL package.
@item Nelson H. F. Beebe
has tested @sc{mdk} in a lot of Unix platforms, suggesting portability
enhancements to the source code.
@item Ryan Schmidt, Agustin Navarro, Ying-Chieh Liao, Adrian Bunk, Baruch Even, and Ronald Cole
ported @sc{mdk} to different platforms, and created and/or maintain
packages for it.
@item Jason Uhlenkott, Andrew Hood, Radu Butnaru, Ruslan Batdalov, WeiZheng, Sascha Wilde, Michael Vernov and Xiaofeng Zhao
reported bugs and suggested fixes to them.
@item Joshua Davies, Eli Bendersky, Milan Bella and Jens Seidel reported bugs on the documentation.
@item Christoph von Nathusius, Stephen Ramsay and Johan Swanljung
tested @sc{mdk} on different platforms, and helped fixing the configuration
process in them.
@item Richard Stallman
suggested various improvements to the documentation and has always
kept an eye on each @sc{mdk} release.
@item @sc{mdk} was inspired by Darius Bacon's
@uref{http://www.accesscom.com/@/~darius/, MIXAL program}.
@end itemize
mdk-1.3.1/doc/mdk_install.texi 0000644 0001750 0001750 00000022120 12622455635 011720 @c -*-texinfo-*-
@c This is part of the GNU MDK Reference Manual.
@c Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006, 2010, 2013
@c Free Software Foundation, Inc.
@c See the file mdk.texi for copying conditions.
@node Installing MDK, MIX and MIXAL tutorial, Acknowledgments, Top
@comment node-name, next, previous, up
@chapter Installing @sc{mdk}
@menu
* Download::
* Requirements::
* Basic installation::
* Emacs support::
* Special configure flags::
* Supported platforms::
@end menu
@node Download, Requirements, Installing MDK, Installing MDK
@comment node-name, next, previous, up
@section Download the source tarball
GNU @sc{mdk} is distributed as a source tarball available for download in
the following @acronym{URL}s:
@itemize @bullet
@item
@url{ftp://ftp.gnu.org/pub/gnu/mdk}
@item
@uref{http://www.gnu.org/prep/ftp.html, GNU mirrors}
@end itemize
The above sites contain the latest stable releases of @sc{mdk}. The
development branch is available as a @uref{http://git-scm.com/,Git}
repository located at@footnote{See
@uref{https://savannah.gnu.org/git/?group=mdk, @sc{mdk}'s Git page} for
more information on using the unstable source tree. Note, however, that
the rest of this manual is about the @emph{stable} release.}
@itemize @bullet
@item
@uref{git://git.savannah.gnu.org/mdk.git}
@end itemize
After you have downloaded the source tarball, unpack it in a directory
of your choice using the command:
@example
tar xfvz mdk-X.Y.tar.gz
@end example
@noindent
where @var{X.Y} stands for the downloaded version (the current stable
release being version @value{VERSION}).
@node Requirements, Basic installation, Download, Installing MDK
@comment node-name, next, previous, up
@section Requirements
In order to build and install @sc{mdk}, you will need the following
libraries installed in your system:
@itemize @minus
@item
@uref{http://www.gtk.org, GLIB 2.16.0} (required)
@item
@uref{http://www.gnu.org/software/flex/flex.html, GNU Flex 2.5} (required)
@item
@uref{http://www.gtk.org, GTK 2.16.0} (optional)
@item
@uref{http://ftp.gnome.org/pub/GNOME/sources/libglade/2.6/, Libglade
2.6.0}
(optional)
@item
@uref{http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html, GNU
Readline}
(optional)
@item
@uref{http://www.gnu.org/software/guile, GNU Libguile 2.0} (optional)
@end itemize
If present, readline and history are used to provide command completion
and history management to the command line MIX virtual machine, @code{mixvm}.
GTK+ and libglade are needed if you want to build the graphical
interface to the MIX virtual machine, @code{gmixvm}. Finally, if
libguile is found, the @sc{mdk} utilities will be compiled with Guile
support and will be extensible using Scheme.
@strong{Please note}: you need both the libraries @emph{and} the
headers; this means both the library package and the @file{-dev} package
if you do not compile your libraries yourself (ex: installing
@file{libgtk2.0-0} and @file{libgtk2.0-0-dev} on Debian).
@node Basic installation, Emacs support, Requirements, Installing MDK
@comment node-name, next, previous, up
@section Basic installation
@sc{mdk} uses GNU Autoconf and Automake tools, and, therefore, should
be built and installed without hassle using the following commands
inside the source directory:
@example
./configure
make
make install
@end example
@noindent
where the last one must be run as root.
The first command, @code{configure}, will setup the makefiles for your
system. In particular, @code{configure} will look for GTK+ and libglade,
and, if they are present, will generate the appropriate makefiles for
building the @code{gmixvm} graphical user interface. Upon completion,
you should see a message with the configuration results like the
following:
@example
*** GNU MDK @value{VERSION} has been successfully configured. ***
Type 'make' to build the following utilities:
- mixasm (MIX assembler)
- mixvm (MIX virtual machine, with readline support,
with guile support)
- gmixvm (mixvm GTK+ GUI, with guile support)
- mixguile (the mixvm guile shell)
@end example
@noindent
where the last lines may be missing if you lack the above mentioned
libraries.
The next command, @code{make}, will actually build the @sc{mdk} programs
in the following locations:
@itemize @minus
@item
@file{mixutils/mixasm}
@item
@file{mixutils/mixvm}
@item
@file{mixgtk/gmixvm}
@item
@file{mixguile/mixguile}
@end itemize
You can run these programs from within their directories, but I
recommend you to install them in proper locations using @code{make
install} from a root shell.
@node Emacs support, Special configure flags, Basic installation, Installing MDK
@comment node-name, next, previous, up
@section Emacs support
@sc{mdk} includes extensive support for Emacs. Upon installation, all
the elisp code is installed in @file{PREFIX/share/mdk}, where
@file{PREFIX} stands for your installation root directory (e.g.
@file{/usr/local}). You can copy the elisp files to a directory that
is in your load-path, or you can add the above directory to it.
Assuming that the installing prefix is @file{/usr/local},
you can do it by adding to your @file{.emacs} file the following line:
@lisp
(setq load-path (cons "/usr/local/share/mdk" load-path))
@end lisp
@code{MIXAL} programs can be written using Emacs and the elisp program
@file{share/mdk/mixal-mode.el}, contributed by @value{PIETER}. It
provides font locking, interactive help, compiling assistance and
invocation of the @code{MIX} virtual machine via a new major mode
called @code{mixal-mode}. To start @code{mixal-mode} automatically
whenever you edit a @code{MIXAL} source file, add the following lines
to your @file{.emacs} file:
@lisp
(autoload 'mixal-mode "mixal-mode" t)
(add-to-list 'auto-mode-alist '("\\.mixal\\'" . mixal-mode))
@end lisp
In addition, @code{mixvm} can be run within an Emacs @acronym{GUD}
buffer using the elisp program @file{share/mdk/mixvm.el}, contributed
by @value{PHILIP}. @file{mixvm.el} provides an interface between
@sc{mdk}'s @code{mixvm} and Emacs, via @acronym{GUD}. Place this file
in your load-path, optionally adding the following line to your
@file{.emacs} file:
@lisp
(autoload 'mixvm "mixvm" "mixvm/gud interaction" t)
@end lisp
@node Special configure flags, Supported platforms, Emacs support, Installing MDK
@comment node-name, next, previous, up
@section Special configure flags
You can fine-tune the configuration process using the following
switches with configure:
@defopt @w{--enable-gui[=yes|no]}
@defoptx --disable-gui
Enables/disables the build of the MIX virtual machine GUI
(@code{gmixvm}). If the required libraries are missing
(@pxref{Requirements}) the configure script with automatically disable
this feature.
@end defopt
@defopt @w{--with-guile[=yes|no]}
@defoptx --without-guile
Enables/disables the Guile support for @code{mixvm} and @code{gmixvm},
and the build of @code{mixguile}. If the
required libraries are missing (@pxref{Requirements}) the configure
script with automatically disable this feature.
@end defopt
@defopt @w{--with-readline[=yes|no]}
@defoptx --without-readline
Enables/disables the GNU Readline support for @code{mixvm}. If the
required libraries are missing (@pxref{Requirements}) the configure
script with automatically disable this feature.
@end defopt
For additional, boilerplate configure options, see the @file{INSTALL}
file, or run
@example
configure --help
@end example
@node Supported platforms, , Special configure flags, Installing MDK
@comment node-name, next, previous, up
@section Supported platforms
GNU MDK has been tested in the following platforms:
@itemize
@item
Debian GNU/Linux 2.2, 2.3, 3.0, 3.1, 3.2, 4.0, 5.0, 6.0, sid
@item
Redhat GNU/Linux 8.0 (Ronald Cole), 7.0 (Agustin Navarro), 6.2
(Roberto Ferrero)
@item
Mandrake 8.0 (Agustin Navarro)
@item
FreeBSD 4.2, 4.3, 4.4, 4.5 (Ying-Chieh Liao), 5.2
@item
Solaris 2.8/gcc 2.95.3 (Stephen Ramsay)
@item
MS Windows 98 SE/Cygwin 1.1.8-2 (Christoph von
Nathusius)@footnote{Caveats: Christoph has only tested @code{mixvm} and
@code{mixasm} on this platform, using @code{gcc} 2.95.3-2, @code{GLIB}
1.2.10 and @code{GNU readline} 4.1-2. He has reported missing history
functionalities on a first try. If you find problems with
history/readline functionality, please try a newer/manually installed
readline version.}
@item
Mac OS X 10.1.2 (Johan Swanljung), Mac OS X 10.4.x, 10.5 (Darwin Port by
Aleix Conchillo).
@item
AMD Athlon, GNU/Linux version 2.4.2-2smp (Red Hat 7.1 (Seawolf)) (N.
H. F. Beebe)
@item
Apple PowerPC G3, GNU/Linux 2.2.18-4hpmac (Red Hat Linux/PPC
2000 Q4) (N. H. F. Beebe)
@item
DEC Alpha, GNU/Linux 2.2.19-6.2.1 (Red Hat 6.2) (N. H. F. Beebe)
@item
Compaq/DEC Alpha OSF/1 4.0F [ONLY after adding rsync's snprintf()
implementation] (N. H. F. Beebe)
@item
IBM PowerPC AIX 4.2 (N. H. F. Beebe)
@item
Intel Pentium III, GNU/Linux 2.4.9-31smp (Red Hat 7.2 (Enigma)) (N. H.
F. Beebe)
@item
SGI Origin 200, IRIX 6.5 (N.
H. F. Beebe)
@item
Sun SPARC, GNU/Linux 2.2.19-6.2.1 (Red Hat 6.2) (N. H. F. Beebe)
@item
Sun SPARC, Solaris 2.8 (N. H. F. Beebe)
@end itemize
@sc{mdk} will probably work on any GNU/Linux or BSD platform. If you
try it in a platform not listed above, please send a mail to
@email{jao@@gnu.org, the author}.
mdk-1.3.1/doc/mdk_findex.texi 0000644 0001750 0001750 00000000461 12112755472 011527 @c -*-texinfo-*-
@c This is part of the GNU MDK Reference Manual.
@c Copyright (C) 2000, 2001, 2003, 2004, 2006
@c Free Software Foundation, Inc.
@c See the file mdk.texi for copying conditions.
@node Instructions and commands, , Concept Index, Top
@unnumbered Instructions and commands
@printindex fn
mdk-1.3.1/doc/mdk_gmixvm.texi 0000644 0001750 0001750 00000032134 13747276503 011573 @c -*-texinfo-*-
@c This is part of the GNU MDK Reference Manual.
@c Copyright (C) 2000, 2001, 2003, 2004, 2006, 2020
@c Free Software Foundation, Inc.
@c See the file mdk.texi for copying conditions.
@node gmixvm, mixguile, mixvm, Top
@comment node-name, next, previous, up
@chapter @code{gmixvm}, the GTK virtual machine
@cindex @code{gmixvm}
@cindex GUI
@cindex GTK+
This chapter describes the graphical MIX virtual machine emulator
shipped with @sc{mdk}. In addition to having all the command-oriented
functionalities of the other virtual machines (@code{mixvm} and
@code{mixguile}), @code{gmixvm} offers you a graphical interface
displaying the status of the virtual machine, the source code of the the
downloaded programs and the contents of the MIX devices.
@menu
* Invoking gmixvm::
* MIXVM console:: Using @code{mixvm} commands.
* MIX virtual machine:: The MIX virtual machine window.
* MIXAL source view:: Viewing the MIXAL source code.
* MIX devices view:: Device output.
* Menu and status bars:: Available menu commands.
@end menu
@node Invoking gmixvm, MIXVM console, gmixvm, gmixvm
@comment node-name, next, previous, up
@section Invoking @code{gmixvm}
If you have built @sc{mdk} with GTK+ support (@pxref{Installing MDK}), a
graphical front-end for the MIX virtual machine will be available in
your system. You can invoke it by typing
@example
gmixvm [-vhuq] [--version] [--help] [--usage] [--noinit]
@end example
@noindent
at your command prompt, where the options have the following meanings:
@defopt -v
@defoptx --version
Prints version and copyleft information and exits.
@end defopt
@defopt -h
@defoptx --help
@defoptx -u
@defoptx --usage
Prints a summary of available options and exits.
@end defopt
@defopt -q
@defoptx --noinit
Do not load the Guile initialisation file @code{~/.mdk/mixguile.scm} at
startup. This file contains any local Scheme code to be executed by the
embedded Guile interpreter at startup (@pxref{Using Scheme in mixvm and
gmixvm}).
@end defopt
Typing @code{gmixvm} or @code{gmixvm -q} at your command prompt, the
main window will appear, offering you a graphical interface to run and
debug your MIX programs.
@image{img/ss_mix, 400pt}
Apart from the menu and status bars, we can distinguish two zones (or
halves) in this main window. In the upper half of @code{gmixvm}'s main
window there is a notebook with three pages, namely,
@itemize
@item
a MIX virtual machine view, which shows you the registers, flags, memory
contents and time statistics of the virtual machine;
@item
a MIXAL source view, which shows the MIXAL file and lets you manage
breakpoints;
@item
a Devices view, which shows you the output to character based MIX block
devices.
@end itemize
@noindent
These three windows can be detached from the notebook, using either
the penultimate toolbar button (which detachs the currently visible
notebook page) or the menu entries under @code{@w{View->Detached windows}}.
Here is an screenshot showing how @code{gmixvm} looks like when running
with a couple of detached windows:
@ifnotinfo
@image{img/ss_split, 420pt}
@end ifnotinfo
On the other hand, the main window's lower half presents you a
@code{mixvm} command prompt and a logging area where results of the
issued commands are presented. These widgets implement a @code{mixvm}
console which offers almost the same functionality as its
@acronym{CLI} counterpart.
When @code{gmixvm} is run, it creates a directory named @file{.mdk} in
your home directory (if it does not already exist). The @file{.mdk}
directory contains the program settings, the device files used by your
MIX programs (@pxref{Devices}), and a command history file.
The following sections describe the above mentioned components of
@code{gmixvm}.
@node MIXVM console, MIX virtual machine, Invoking gmixvm, gmixvm
@comment node-name, next, previous, up
@section MIXVM console
In the lower half of the @code{gmixvm} main window, you will find a
command text entry and, above it, an echo area. These widgets offer you
the same functionality as its @acronym{CLI} counterpart, @code{mixvm}
(@pxref{mixvm}). You can issue almost all @code{mixmv} commands at the
@code{gmixvm}'s command prompt in order to manipulate the MIX virtual
machine. Please refer to @xref{mixvm}, for a description of these
commands, and to @xref{Getting started}, for a tutorial on using the MIX
virtual machine. The command prompt offers command line completion for
partially typed commands using the @key{TAB} key; e.g., if you type
@example
lo @key{TAB}
@end example
@noindent
the command is automatically completed to @code{load}. If multiple
completions are available, they will be shown in the echo area. Thus,
typing
@example
p @key{TAB}
@end example
@noindent
will produce the following output on the echo area:
@example
Completions:
pc psym preg pflags pall
pmem
@end example
@noindent
which lists all the available commands starting with @code{p}. In
addition, the command prompt maintains a history of typed commands,
which can be recovered using the arrow up and down keys. As mentioned
above, a file containing previous sessions' commands is stored in the
configuration directory @file{~/.mdk}, and reloaded every time you start
@code{gmixvm}.
You can change the font used to display the issued commands and the
messages in the echo area using the @code{@w{Settings->Change font->Command
prompt}} and @code{@w{Settings->Change font->Command log}} menu commands.
@node MIX virtual machine, MIXAL source view, MIXVM console, gmixvm
@comment node-name, next, previous, up
@section MIX virtual machine
The first notebook's page displays the current status of the virtual
machine. There you can find the registers' contents, the value of the
comparison and overflow flags, the location pointer, a list with all MIX
memory cells and their contents, and the time statistics (including
total uptime, elapsed time since the last run command and total
execution time for the currently loaded MIX program).
If you click any register entry, you will be prompted for a new register's
contents.
The next figure shows the enter word dialog.
@ifnotinfo
@image{img/ss_worddlg, 250pt}
@end ifnotinfo
In the same manner, click on any address of the memory cells list to be
prompted for the new contents of the clicked cell. If you click the
address column's title, a dialog asking you for a memory address will
appear; if you introduce a valid address, this will be the first cell
displayed in the scrollable list after you click the OK button.
The register contents are shown as a list of MIX bytes plus sign. If you
place the mouse pointer over any of them, the decimal value of this MIX
word will appear inside a tooltip.
You can change the font used to display the MIX virtual machine contents
using the @code{@w{Settings->Change font->MIX}} menu command.
@node MIXAL source view, MIX devices view, MIX virtual machine, gmixvm
@comment node-name, next, previous, up
@section MIXAL source view
The second notebook's page, dubbed Source, shows you the MIXAL source of
the currently loaded MIX file.
@ifnotinfo
@image{img/ss_mixal, 400pt}
@end ifnotinfo
The information is presented in four columns. The first column
displays little icons showing the current program pointer and any set
breakpoints. The second and third columns show the address and memory
contents of the compiled MIX instruction, while the last one displays
its corresponding MIXAL representation, together with the source file
line number. You can set/unset breakpoints by clicking on any line
that has an associated memory address.
You can change the font used to display the MIXAL source code
using the @code{@w{Settings->Change font->MIXAL}} menu command.
@node MIX devices view, Menu and status bars, MIXAL source view, gmixvm
@comment node-name, next, previous, up
@section MIX devices view
The last notebook page, dubbed Devices, shows you the output/input
to/from MIX block devices (the console, line printer, paper tape,
disks, card and tapes @pxref{Devices}) produced by the running
program.
@ifnotinfo
@image{img/ss_devices, 400pt}
@end ifnotinfo
Input device contents is read from files located in the @file{~/.mdk}
directory, and the output is also written to files at the same
location. Note that device tabs will appear as they are used by the MIX
program being run, and that loading a new MIX program will close all
previously open devices.
The input/output for binary block devices (tapes and disks) is a list
of MIX words, which can be displayed either in decimal or word format
(e.g. @w{- 67} or @w{- 00 00 00 01 03}). The format used by
@code{gmixvm} can be configured using the @code{@w{Settings->Device output}}
menu command for each binary device.
You can change the font used to display the devices content
using the @code{@w{Settings->Change font->Devices}} menu command.
@node Menu and status bars, , MIX devices view, gmixvm
@comment node-name, next, previous, up
@section Menu and status bars
The menu bar gives you access to the following commands:
@deffn File Load...
Opens a file dialog that lets you specify a binary MIX file to be loaded
in the virtual machine's memory. It is equivalent to the @code{mixvm}'s
@code{load} command (@pxref{File commands}).
@end deffn
@deffn File Edit...
Opens a file dialog that lets your specify a MIXAL source file to be
edited. It is equivalent to the @code{mixvm}'s @code{edit} command
(@pxref{File commands}). The program used for editing can be specified
using the menu entry @code{@w{Settings->External programs}}, or using the
@code{mixvm} command @code{sedit}.
@end deffn
@deffn File Compile...
Opens a file dialog that lets your specify a MIXAL source file to be
compiled. It is equivalent to the @code{mixvm}'s @code{compile} command
(@pxref{File commands}). The command used for compiling can be specified
using the menu entry @code{@w{Settings->External programs}}, or using the
@code{mixvm} command @code{sasm}.
@end deffn
@deffn File Exit
Exits the application.
@end deffn
@deffn Debug Run
Runs the currently loaded MIX program, up to the next breakpoint. It is
equivalent to the @code{mixvm}'s @code{run} command (@pxref{Debug
commands}).
@end deffn
@deffn Debug Next
Executes the next MIX instruction. It is equivalent to the
@code{mixvm}'s @code{next} command (@pxref{Debug commands}).
@end deffn
@deffn Debug @w{Clear breakpoints}
Clears all currently set breakpoints. It is equivalent to the
@code{mixvm}'s @code{cabp} command.
@end deffn
@deffn Debug Symbols...
Opens a dialog showing the list of symbols defined in the currently
loaded MIX program. The font used to display this list can be
customised using the meny entry @code{@w{Settings->Change font->Symbol
list}}.
@ifnotinfo
@image{img/ss_symbols, 250pt}
@end ifnotinfo
@end deffn
@deffn View @w{Toolbar(s)}
Toggles the toolbar(s) in the @code{gmixvm} window(s) (when notebook
pages are detached, each one has its own toolbar).
@end deffn
@deffn View @w{Detached windows} @w{Virtual machine}
@deffnx View @w{Detached windows} Source
@deffnx View @w{Detached windows} Devices
These toggles let you detach (or re-attach) the corresponding notebook
page.
@end deffn
@deffn Settings @w{Change font}
Lets you change the font used in the various @code{gmixv} widgets
(i.e. commad prompt, command log, Virtual machine, Source, Devices and
Symbol list). There is also an entry (@code{All}) to change all fonts
at once.
@end deffn
@deffn Settings @w{Device output...}
Opens a dialog that lets you specify which format shall be used to show
the contents of MIX binary block devices.
@ifnotinfo
@image{img/ss_devform, 250pt}
@end ifnotinfo
The available formats are decimal (e.g. @w{-1234}) and MIX word
(e.g. @w{- 00 00 00 19 18}).
@end deffn
@deffn Settings @w{Devices dir...}
Opens a dialog that lets you choose where the MIX device files will be
stored (@file{~/.mdk} is the default location).
@ifnotinfo
@image{img/ss_devdir, 250pt}
@end ifnotinfo
You can also specify the devices directory using the @code{mixvm}
command @code{sddir} (@pxref{Configuration commands}).
@end deffn
@deffn Settings @w{External programs...}
This menu command opens a dialog that lets you specify the commands used
for editing and compiling MIXAL source files.
@ifnotinfo
@image{img/ss_extprog, 250pt}
@end ifnotinfo
The commands are specified as template strings, where the control
substring @code{%s} will be substituted by the actual file name. Thus,
if you want to edit programs using @code{vi} running in an @code{xterm},
you must enter the command template @code{@w{xterm -e vi %s}} in the
corresponding dialog entry. These settings can also be changed using the
@code{mixvm} commands @code{sedit} and @code{sasm} (@pxref{Configuration
commands}).
@end deffn
@deffn Settings Save
Saves the current settings.
@end deffn
@deffn Settings @w{Save on exit}
Mark this checkbox if you want @code{gmixvm} to save its settings
every time you quit the program.
@end deffn
@deffn Help About...
Shows information about @code{gmixvm}'s version and copyright.
@end deffn
On the other hand, the status bar displays the name of the last loaded
MIX file. In addition, when the mouse pointer is over a MIXAL source
file line that contains symbols, a list of these symbols with their
values will appear in the status bar.
mdk-1.3.1/doc/mdk_intro.texi 0000644 0001750 0001750 00000006163 12622455635 011416 @c -*-texinfo-*-
@c This is part of the GNU MDK Reference Manual.
@c Copyright (C) 2000, 2001, 2003, 2004, 2006
@c Free Software Foundation, Inc.
@c See the file mdk.texi for copying conditions.
@node Introduction, Acknowledgments, Top, Top
@comment node-name, next, previous, up
@unnumbered Introduction
@cindex Introduction
In his book series @cite{The Art of Computer Programming} (published by
Addison Wesley), D. Knuth uses an imaginary computer, the MIX, and its
associated machine-code and assembly languages to illustrate the
concepts and algorithms as they are presented.
The MIX's architecture is a simplified version of those found in real
CISC CPUs, and the MIX assembly language (MIXAL) provides a set of
primitives that will be very familiar to any person with a minimum
experience in assembly programming. The MIX/MIXAL definition is powerful
and complete enough to provide a virtual development platform for
writing quite complex programs, and close enough to real computers to be
worth using when learning programming techniques. At any rate, if you
want to learn or improve your programming skills, a MIX development
environment would come in handy.
The @sc{mdk} package aims at providing such virtual development
environment on a GNU box. Thus, @sc{mdk} offers you a set of utilities
to simulate the MIX computer and to write, compile, run and debug MIXAL
programs. As of version @value{VERSION}, @sc{mdk} includes
the following programs:
@table @code
@item mixasm
MIXAL assembler. Assembler which translates MIXAL source files into
programs that can be run (and debugged) by @code{mixvm}, @code{mixguile}
or @code{gmixvm}.
@item mixvm
MIX virtual machine. Emulation of the MIX computer with a @acronym{CLI}.
@item gmixvm
A GTK+ GUI for the MIX virtual machine. Provides all of @code{mixvm}
functionality accessible through a graphical interface.
@item mixguile
A Guile shell, with an embedded MIX virtual machine and built-in
commands to manipulate it using Scheme.
@item mixal-mode.el
An Emacs major mode for MIXAL source files editing, providing syntax
highlighting, documentation lookup and invocation of @code{mixvm}
within Emacs.
@item mixvm.el
This elisp program allows running @code{mixvm} inside an Emacs GUD
buffer, providing concurrent edition and debugging of MIXAL programs.
@end table
@code{mixvm} and @code{gmixvm} implement a simulator of the MIX
computer, giving you a virtual machine for executing and debugging MIX
programs. These binary programs could be written by hand, but it is
easier to produce them compiling MIXAL source files, using the MIXAL
assembler @code{mixasm}. On the other hand, @code{mixguile} offers you
the possibility of manipulating a MIX virtual machine through a set of
Scheme functions, so that you can use this programming language to
interact with the virtual machine. In addition, @code{mixvm} and
@code{gmixvm} are also able to interpret Scheme scripts (using an
embedded Guile interpreter), that is, you can use Scheme as an extension
language to add new functionalities to these programs.
This manual gives you a tutorial of MIX and MIXAL, and a thorough
description of the use of the @sc{mdk} utilities.
mdk-1.3.1/doc/img/ 0000775 0001750 0001750 00000000000 15065042311 007350 5 mdk-1.3.1/doc/img/ss_extprog.jpg 0000644 0001750 0001750 00000024052 13747275312 012206 ÿØÿà JFIF H H ÿÛ C !"$"$ÿÛ CÿÀ v¢" ÿÄ ÿÄ G !"”Ó1TU#2V•£Ò4AQat35–´&6Bqrs±²$%CSbÿÄ ÿÄ & !Að1QaÑ2q‘ñÿÚ ? ýaJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJRJÔvã·”n[¦Ú¢G]AUD\*€ª"áQqüÒ±ö›? tû²Gä Ý¥i{MŸ„º}Ù#òSÚlü%ÓîÉ’ƒv•¥í6~é÷dÉOi³ð—O»$~J
ÚV—´ÙøK§Ý’?%=¦ÏÂ]>ì‘ù(7iZ^Ógá.ŸvHü”ö›? tû²Gä Ý¥i{MŸ„º}Ù#òSÚlü%ÓîÉ’ƒv•¥í6~é÷dÉOi³ð—O»$~J
ÚV—´ÙøK§Ý’?%=¦ÏÂ]>ì‘ù(7iZ^Ógá.ŸvHü”ö›? tû²Gä Ý¥i{MŸ„º}Ù#òV'vŒØŽ±qi±L‘¹o|DS÷ªª†?šÐoÒ” W8×½¦~kG4æíŽÜÄÞ{þ¥ög/+†ÆÇÍûx2K”Æñé]ª·ÍôíNö¡·jÛõŠTˆLC| „CmÐdÞ0UGØqQQ_sÜ¨ŠŠ:PikžÐ-öI¬Ú ;Ïw+¥¶¬G–†L¦[$'E6œNˆ‘"û—
žøÝÚæŸ¾[n²¥=(#ZÑ×/dL`œxÎ#£øÎB 3¼Ü!ÚI¹ ¦/]ŸÛîw×nky¼ÄjEÂÊTî4‘äIŠmNæÔÓ£
’" §L¢-hZ»)³Û,ÏYbÞï£nr<0àWðHˆÜvØ–$oG…"³Ó