mirror of
https://github.com/GaloisInc/cryptol.git
synced 2024-11-25 20:04:14 +03:00
Initial import from internal repo
This commit is contained in:
commit
ba0a0e8576
17
.gitignore
vendored
Normal file
17
.gitignore
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
*.pyc
|
||||
*\#*
|
||||
*~
|
||||
.DS_Store
|
||||
.cabal-sandbox
|
||||
cabal.sandbox.config
|
||||
dist
|
||||
results.xml
|
||||
|
||||
# don't check in generated documentation
|
||||
docs/Cryptol.pdf
|
||||
docs/CryptolPrims.pdf
|
||||
docs/Syntax.pdf
|
||||
docs/Version2Changes.pdf
|
||||
|
||||
# don't check in distribution files
|
||||
cryptol-2.*
|
30
LICENSE
Normal file
30
LICENSE
Normal file
@ -0,0 +1,30 @@
|
||||
Copyright (c) 2013-2014 Galois Inc.
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in
|
||||
the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
* Neither the name of Galois, Inc. nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this
|
||||
software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
||||
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
150
Makefile
Normal file
150
Makefile
Normal file
@ -0,0 +1,150 @@
|
||||
UNAME := $(shell uname -s)
|
||||
ARCH := $(shell uname -m)
|
||||
|
||||
TESTS ?= issues regression renamer
|
||||
|
||||
CABAL_FLAGS := -j
|
||||
|
||||
CABAL_EXE := cabal
|
||||
CABAL := $(CABAL_EXE) $(CABAL_FLAGS)
|
||||
CS := ./.cabal-sandbox
|
||||
CS_BIN := $(CS)/bin
|
||||
|
||||
# Used only for windows, to find the right Program Files. Right now we
|
||||
# only cut 32-bit releases.
|
||||
PROGRAM_FILES = Program\ Files
|
||||
# Windows installer tools; assumes running on Cygwin and using WiX 3.7
|
||||
WiX := /cygdrive/c/${PROGRAM_FILES}/WiX\ Toolset\ v3.7
|
||||
CANDLE := ${WiX}/bin/candle.exe
|
||||
HEAT := ${WiX}/bin/heat.exe
|
||||
LIGHT := ${WiX}/bin/light.exe
|
||||
|
||||
REV ?= $(shell git rev-parse --short=7 HEAD || echo "unknown")
|
||||
VERSION := $(shell grep -i ^Version cryptol.cabal | awk '{ print $$2}')
|
||||
PKG := cryptol-${VERSION}-${UNAME}_${REV}
|
||||
|
||||
# Windows-specific stuff
|
||||
ifneq (,$(findstring _NT,${UNAME}))
|
||||
DIST := ${PKG}.msi
|
||||
EXE_EXT := .exe
|
||||
adjust-path = '$(shell cygpath -w $1)'
|
||||
else
|
||||
DIST := ${PKG}.tar.gz ${PKG}.zip
|
||||
EXE_EXT :=
|
||||
adjust-path = '$1'
|
||||
endif
|
||||
|
||||
.PHONY: all
|
||||
all: ${CS_BIN}/cryptol
|
||||
|
||||
.PHONY: docs
|
||||
docs:
|
||||
(cd docs; make)
|
||||
|
||||
.PHONY: dist
|
||||
dist: ${DIST}
|
||||
|
||||
.PHONY: tarball
|
||||
tarball: ${PKG}.tar.gz
|
||||
|
||||
.PHONY: zip
|
||||
zip: ${PKG}.zip
|
||||
|
||||
.PHONY: msi
|
||||
msi: ${PKG}.msi
|
||||
|
||||
${CS}:
|
||||
$(CABAL_EXE) sandbox init
|
||||
|
||||
# order-only dependency: we just want the sandbox to exist
|
||||
${CS_BIN}/alex: | ${CS}
|
||||
$(CABAL) install alex
|
||||
|
||||
# order-only dependency: we just want the sandbox to exist
|
||||
${CS_BIN}/happy: | ${CS}
|
||||
$(CABAL) install happy
|
||||
|
||||
src/GitRev.hs:
|
||||
sh configure
|
||||
|
||||
# It would be nice to refine these dependencies some in order to avoid
|
||||
# unnecessary rebuilds, but for now it's safest to just always cabal
|
||||
# install.
|
||||
.PHONY: ${CS_BIN}/cryptol
|
||||
${CS_BIN}/cryptol: ${CS_BIN}/alex ${CS_BIN}/happy | ${CS}
|
||||
$(CABAL) install .
|
||||
|
||||
${PKG}: ${CS_BIN}/cryptol
|
||||
mkdir -p ${PKG}/bin
|
||||
mkdir -p ${PKG}/lib
|
||||
mkdir -p ${PKG}/doc/examples
|
||||
cp ${CS_BIN}/cryptol ${PKG}/bin/cryptol
|
||||
cp -R docs/*.markdown ${PKG}/doc
|
||||
cp -R docs/*.pdf ${PKG}/doc
|
||||
cp -R lib/* ${PKG}/lib
|
||||
cp docs/ProgrammingCryptol/aes/AES.cry ${PKG}/doc/examples
|
||||
cp docs/ProgrammingCryptol/enigma/Enigma.cry ${PKG}/doc/examples
|
||||
cp examples/DES.cry ${PKG}/doc/examples
|
||||
cp examples/Cipher.cry ${PKG}/doc/examples
|
||||
cp examples/DEStest.cry ${PKG}/doc/examples
|
||||
cp examples/Test.cry ${PKG}/doc/examples
|
||||
cp examples/SHA1.cry ${PKG}/doc/examples
|
||||
cp examples/simon.cry ${PKG}/doc/examples
|
||||
cp LICENSE ${PKG}/doc
|
||||
|
||||
${PKG}.tar.gz: ${PKG}
|
||||
tar -czvf $@ $<
|
||||
|
||||
${PKG}.zip: ${PKG}
|
||||
zip -r $@ $<
|
||||
|
||||
${PKG}.msi: ${PKG} win32/cryptol.wxs
|
||||
${HEAT} dir ${PKG} -o allfiles.wxs -nologo -var var.pkg -ag -wixvar -cg ALLFILES -srd -dr INSTALLDIR -sfrag
|
||||
${CANDLE} -ext WixUIExtension -ext WixUtilExtension -dversion=${VERSION} -dpkg=${PKG} win32/cryptol.wxs
|
||||
${CANDLE} -ext WixUIExtension -ext WixUtilExtension -dversion=${VERSION} -dpkg=${PKG} allfiles.wxs
|
||||
${LIGHT} -ext WixUIExtension -ext WixUtilExtension -sval -o $@ cryptol.wixobj allfiles.wixobj
|
||||
rm -f allfiles.wxs
|
||||
rm -f *.wixobj
|
||||
rm -f *.wixpdb
|
||||
|
||||
${CS_BIN}/cryptol-test-runner: \
|
||||
$(CS_BIN)/cryptol \
|
||||
$(CURDIR)/tests/Main.hs \
|
||||
$(CURDIR)/tests/cryptol-test-runner.cabal
|
||||
$(CABAL) install ./tests
|
||||
|
||||
.PHONY: test
|
||||
test: ${CS_BIN}/cryptol-test-runner
|
||||
( cd tests && \
|
||||
echo "Testing on $(UNAME)-$(ARCH)" && \
|
||||
$(realpath $(CS_BIN)/cryptol-test-runner) \
|
||||
$(foreach t,$(TESTS),-d $t) \
|
||||
-c $(call adjust-path,$(realpath $(CS_BIN)/cryptol$(EXE_EXT))) \
|
||||
-r output \
|
||||
-T --hide-successes \
|
||||
-T --jxml=$(call adjust-path,$(CURDIR)/results.xml) \
|
||||
)
|
||||
|
||||
.PHONY: notebook
|
||||
notebook: ${CS_BIN}/cryptol
|
||||
cd notebook && ./notebook.sh
|
||||
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
cabal clean
|
||||
rm -f src/GitRev.hs
|
||||
rm -f $(CS_BIN)/cryptol
|
||||
rm -f $(CS_BIN)/cryptol-test-suite
|
||||
rm -f $(CS_BIN)/cryptolnb
|
||||
rm -rf cryptol-${VERSION}*/
|
||||
rm -rf cryptol-${VERSION}*.tar.gz
|
||||
rm -rf cryptol-${VERSION}*.zip
|
||||
rm -rf cryptol-${VERSION}*.msi
|
||||
|
||||
.PHONY: squeaky
|
||||
squeaky: clean
|
||||
-$(CABAL_EXE) sandbox delete
|
||||
(cd docs; make clean)
|
||||
rm -rf dist
|
||||
rm -rf tests/dist
|
177
README.md
Normal file
177
README.md
Normal file
@ -0,0 +1,177 @@
|
||||
# Cryptol, version 2
|
||||
|
||||
This version of Cryptol is (C) 2013-2014 Galois, Inc., and
|
||||
distributed under a standard, three-clause BSD license. Please see
|
||||
the file LICENSE, distributed with this software, for specific
|
||||
terms and conditions.
|
||||
|
||||
# What is Cryptol?
|
||||
|
||||
The Cryptol specification language was designed by Galois for the
|
||||
NSA's Trusted Systems Research Group as a public standard for
|
||||
specifying cryptographic algorithms. A Cryptol reference specification
|
||||
can serve as the formal documentation for a cryptographic module.
|
||||
Unlike current specification mechanisms, Cryptol is fully executable,
|
||||
allowing designers to experiment with their programs incrementally as
|
||||
their designs evolve.
|
||||
|
||||
This release is an interpreter for version 2 of the Cryptol
|
||||
language. The interpreter includes a `:check` command, which tests
|
||||
predicates written in Cryptol against randomly-generated test vectors
|
||||
(in the style of
|
||||
[QuickCheck](http://hackage.haskell.org/package/QuickCheck). There is
|
||||
also a `:prove` command, which calls out to SMT solvers, such as
|
||||
Yices, Z3, or CVC4, to prove predicates for all possible inputs.
|
||||
|
||||
# Getting Cryptol Binaries
|
||||
|
||||
Cryptol binaries for Mac OS X, Linux, and Windows are available from
|
||||
the GitHub
|
||||
[releases page](https://github.com/GaloisInc/cryptol/releases). Mac OS
|
||||
X and Linux binaries are distributed as a tarball which you can
|
||||
extract to a location of your choice. Windows binaries are distributed
|
||||
as an `.msi` installer package which places a shortcut to the Cryptol
|
||||
interpreter in the Start menu.
|
||||
|
||||
Cryptol currently depends on the
|
||||
[CVC4 SMT solver](http://cvc4.cs.nyu.edu/) to solve constraints during
|
||||
typechecking, and as the default solver for the `:sat` and `:prove`
|
||||
commands. You can download CVC4 binaries for a variety of platforms
|
||||
from their [download page](http://cvc4.cs.nyu.edu/downloads/).
|
||||
|
||||
# Building Cryptol From Source
|
||||
|
||||
In addition to the binaries, the Cryptol source is available publicly
|
||||
on [GitHub](https://github.com/GaloisInc/cryptol).
|
||||
|
||||
Cryptol builds and runs on various flavors of Linux, Mac OS X, and
|
||||
Windows. We regularly build and test it in the following environments:
|
||||
|
||||
- Mac OS X 10.9 64-bit
|
||||
- CentOS 5 32/64-bit
|
||||
- CentOS 6 32/64-bit
|
||||
- Windows XP 32-bit
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Cryptol is developed using GHC 7.6.3 and cabal-install 1.18. While you
|
||||
can install these independently, the easiest way to get the correct
|
||||
versions is to:
|
||||
|
||||
1. Install [Haskell Platform 2013.2.0.0](http://www.haskell.org/platform/)
|
||||
|
||||
**Mac Users**: the current version of the Haskell Platform has
|
||||
some incompatibilities with Mac OS X 10.9; it is easier to install
|
||||
GHC, cabal-install, alex, and happy from
|
||||
[MacPorts](https://www.macports.org/) or
|
||||
[Homebrew](http://brew.sh/).
|
||||
|
||||
1. Run `cabal update`
|
||||
|
||||
1. Run `cabal install cabal-install`
|
||||
|
||||
1. Add cabal-install's binary path to your PATH variable (usually `~/.cabal/bin`)
|
||||
|
||||
Some supporting non-Haskell libraries are required to build
|
||||
Cryptol. Most should already be present for your operating system, but
|
||||
you may need to install the following:
|
||||
|
||||
- [The GNU Multiple Precision Arithmetic Library (GMP)](https://gmplib.org/)
|
||||
- [ncurses](https://www.gnu.org/software/ncurses/)
|
||||
|
||||
## Building Cryptol
|
||||
|
||||
From the Cryptol source directory, run:
|
||||
|
||||
make
|
||||
|
||||
This will build Cryptol in place. From there, there are additional targets:
|
||||
|
||||
- `make test`: run the regression test suite
|
||||
- `make docs`: build the Cryptol documentation (requires
|
||||
[pandoc](http://johnmacfarlane.net/pandoc/) and
|
||||
[TeX Live](https://www.tug.org/texlive/))
|
||||
- `make tarball`: build a tarball with a relocatable Cryptol binary and documentation
|
||||
- `make dist`: build a platform-specific distribution. On all
|
||||
platforms except Windows, this is currently equivalent to `make
|
||||
tarball`. On Windows, this will build an `.msi` package using
|
||||
[WiX Toolset 3.7](http://wixtoolset.org/), which must be installed
|
||||
separately.
|
||||
|
||||
## Installing Cryptol
|
||||
|
||||
Aside from the `docs` target, these will leave you with a Cryptol
|
||||
binary at `.cabal-sandbox/bin/cryptol` in your source directory. You
|
||||
can either use that binary directly, or use the results of `tarball`
|
||||
or `dist` to install Cryptol in a location of your choice.
|
||||
|
||||
# Contributing
|
||||
|
||||
We believe that anyone who uses Cryptol is making an important
|
||||
contribution toward making Cryptol a better tool. There are many ways
|
||||
to get involved.
|
||||
|
||||
## Users
|
||||
|
||||
If you run into a bug in Cryptol, if something doesn't make sense in
|
||||
the documentation, if you think something could be better, or if you
|
||||
just have a cool use of Cryptol that you'd like to share with us, use
|
||||
the issues page on [GitHub](https://github.com/GaloisInc/cryptol), or
|
||||
send email to <cryptol@galois.com>.
|
||||
|
||||
## Developers
|
||||
|
||||
If you plan to do development work on the Cryptol interpreter, please
|
||||
make a fork of the GitHub repository and send along pull
|
||||
requests. This makes it easier for us to track development and to
|
||||
incorprate your changes.
|
||||
|
||||
### Repository Structure
|
||||
|
||||
- `/cryptol`: Haskell sources for the front-end `cryptol` executable
|
||||
and read-eval-print loop
|
||||
- `/docs`: LaTeX and Markdown sources for the Cryptol documentation
|
||||
- `/examples`: Cryptol sources implementing several interesting
|
||||
algorithms
|
||||
- `/lib`: Cryptol standard library sources
|
||||
- `/notebook`: Experimental Cryptol IPython Notebook implementation
|
||||
- `/sbv`: Haskell sources for the `sbv` library, derived from Levent
|
||||
Erkok's [`sbv` library](http://leventerkok.github.io/sbv/) (see
|
||||
`/sbv/LICENSE`)
|
||||
- `/src`: Haskell sources for the `cryptol` library (the bulk of the
|
||||
implementation)
|
||||
- `/tests`: Haskell sources for the Cryptol regression test suite, as
|
||||
well as the Cryptol sources and expected outputs that comprise that
|
||||
suite
|
||||
|
||||
|
||||
# Where to Look Next
|
||||
|
||||
The `docs` directory of the installation package contains an
|
||||
introductory book, the `examples` directory contains a number of
|
||||
algorithms specified in Cryptol. We host a Cryptol mailing list, which
|
||||
you can join (TODO). If you find bugs, or would like to submit a
|
||||
patch, please use GitHub to report an issue or send us a pull request.
|
||||
|
||||
If you are familiar with version 1 of Cryptol, you should read the
|
||||
`Version2Changes` document in the `docs` directory.
|
||||
|
||||
Cryptol is still under active development at Galois. We are also
|
||||
building tools that consume both Cryptol specifications and
|
||||
implementations in (for example) C or Java, and can (with some amount
|
||||
of work) allow you to verify that an implementation meets its
|
||||
specification. Email us at <cryptol@galois.com> if you're interested
|
||||
in these capabilities.
|
||||
|
||||
# Thanks!
|
||||
|
||||
We hope that Cryptol is useful as a tool for educators and students,
|
||||
commercial and open source authors of cryptographic implementations,
|
||||
and by cryptographers to
|
||||
|
||||
* specify cryptographic algorithms
|
||||
* check or prove properties of algorithms
|
||||
* generate test vectors for testing implementations
|
||||
* experiment with new algorithms
|
||||
|
||||
|
10
Setup.hs
Normal file
10
Setup.hs
Normal file
@ -0,0 +1,10 @@
|
||||
-- |
|
||||
-- Module : $Header$
|
||||
-- Copyright : (c) 2013-2014 Galois, Inc.
|
||||
-- License : BSD3
|
||||
-- Maintainer : cryptol@galois.com
|
||||
-- Stability : provisional
|
||||
-- Portability : portable
|
||||
|
||||
import Distribution.Simple
|
||||
main = defaultMain
|
32
configure
vendored
Executable file
32
configure
vendored
Executable file
@ -0,0 +1,32 @@
|
||||
#!/bin/sh
|
||||
|
||||
has_git=`which git 2>/dev/null`
|
||||
if test -d .git -a -n "$has_git"; then
|
||||
HASH=`git rev-parse HEAD`
|
||||
BRANCH=`git rev-parse --abbrev-ref HEAD`
|
||||
|
||||
# Checks if there are any lines in git status
|
||||
if test -z "`git status --porcelain`"; then
|
||||
DIRTY=False
|
||||
else
|
||||
DIRTY=True
|
||||
fi
|
||||
else
|
||||
HASH="UNKNOWN"
|
||||
BRANCH="UNKNOWN"
|
||||
# well, we're not building from any git...
|
||||
DIRTY="False"
|
||||
fi
|
||||
|
||||
cat > src/GitRev.hs <<EOF
|
||||
module GitRev (hash, branch, dirty) where
|
||||
|
||||
hash :: String
|
||||
hash = "$HASH"
|
||||
|
||||
branch :: String
|
||||
branch = "$BRANCH"
|
||||
|
||||
dirty :: Bool
|
||||
dirty = $DIRTY
|
||||
EOF
|
198
cryptol.cabal
Normal file
198
cryptol.cabal
Normal file
@ -0,0 +1,198 @@
|
||||
Name: cryptol-parser
|
||||
Version: 2.0.0
|
||||
Synopsis: Cryptol: The Language of Cryptography
|
||||
License: BSD3
|
||||
Author: Galois, Inc.
|
||||
Maintainer: cryptol@galois.com
|
||||
Copyright: 2013-2014 Galois Inc.
|
||||
Category: Language
|
||||
Build-type: Configure
|
||||
Cabal-version: >= 1.18
|
||||
|
||||
data-files: lib/Cryptol.cry
|
||||
|
||||
flag static
|
||||
default: False
|
||||
description: Create a statically-linked binary
|
||||
|
||||
library
|
||||
Build-depends: base >= 4.6,
|
||||
array >= 0.4,
|
||||
containers >= 0.5,
|
||||
deepseq >= 1.3,
|
||||
directory >= 1.2,
|
||||
executable-path >= 0.0.3,
|
||||
filepath >= 1.3,
|
||||
GraphSCC >= 1.0.4,
|
||||
monadLib >= 3.7.2,
|
||||
mtl >= 2.1,
|
||||
old-time >= 1.1,
|
||||
presburger >= 1.1,
|
||||
pretty >= 1.1,
|
||||
process >= 1.2,
|
||||
QuickCheck >= 2.7,
|
||||
random >= 1.0.1,
|
||||
smtLib >= 1.0.7,
|
||||
syb >= 0.4,
|
||||
text >= 1.1,
|
||||
transformers >= 0.3,
|
||||
utf8-string >= 0.3
|
||||
|
||||
Build-tools: alex, happy
|
||||
hs-source-dirs: src, sbv
|
||||
|
||||
Exposed-modules: Cryptol.Prims.Syntax,
|
||||
Cryptol.Prims.Types,
|
||||
Cryptol.Prims.Eval,
|
||||
Cryptol.Prims.Doc,
|
||||
|
||||
Cryptol.Parser,
|
||||
Cryptol.Parser.Lexer,
|
||||
Cryptol.Parser.AST,
|
||||
Cryptol.Parser.Position,
|
||||
Cryptol.Parser.Names,
|
||||
Cryptol.Parser.NoPat,
|
||||
Cryptol.Parser.NoInclude,
|
||||
Cryptol.Parser.Utils,
|
||||
Cryptol.Parser.Unlit,
|
||||
|
||||
Cryptol.Utils.PP,
|
||||
Cryptol.Utils.Panic,
|
||||
Cryptol.Utils.Debug,
|
||||
Cryptol.Version,
|
||||
|
||||
Cryptol.ModuleSystem,
|
||||
Cryptol.ModuleSystem.Base,
|
||||
Cryptol.ModuleSystem.Env,
|
||||
Cryptol.ModuleSystem.Interface,
|
||||
Cryptol.ModuleSystem.Monad,
|
||||
Cryptol.ModuleSystem.NamingEnv,
|
||||
Cryptol.ModuleSystem.Renamer,
|
||||
|
||||
Cryptol.TypeCheck,
|
||||
Cryptol.TypeCheck.AST,
|
||||
Cryptol.TypeCheck.Monad,
|
||||
Cryptol.TypeCheck.Infer,
|
||||
Cryptol.TypeCheck.InferTypes,
|
||||
Cryptol.TypeCheck.Kind,
|
||||
Cryptol.TypeCheck.Subst,
|
||||
Cryptol.TypeCheck.Instantiate,
|
||||
Cryptol.TypeCheck.Unify,
|
||||
Cryptol.TypeCheck.Depends,
|
||||
Cryptol.TypeCheck.PP,
|
||||
Cryptol.TypeCheck.Solve,
|
||||
Cryptol.TypeCheck.TypeMap,
|
||||
Cryptol.TypeCheck.Defaulting,
|
||||
|
||||
Cryptol.TypeCheck.Solver.Eval,
|
||||
Cryptol.TypeCheck.Solver.FinOrd,
|
||||
Cryptol.TypeCheck.Solver.InfNat,
|
||||
Cryptol.TypeCheck.Solver.Interval,
|
||||
Cryptol.TypeCheck.Solver.Smtlib,
|
||||
Cryptol.TypeCheck.Solver.Numeric,
|
||||
Cryptol.TypeCheck.Solver.Class,
|
||||
Cryptol.TypeCheck.Solver.Selector,
|
||||
Cryptol.TypeCheck.Solver.CrySAT,
|
||||
Cryptol.TypeCheck.Solver.Utils,
|
||||
|
||||
Cryptol.Transform.MonoValues,
|
||||
Cryptol.Transform.Specialize,
|
||||
|
||||
Cryptol.Eval,
|
||||
Cryptol.Eval.Env,
|
||||
Cryptol.Eval.Error,
|
||||
Cryptol.Eval.Type,
|
||||
Cryptol.Eval.Value,
|
||||
|
||||
Cryptol.Testing.Random,
|
||||
Cryptol.Testing.Exhaust
|
||||
|
||||
Cryptol.Symbolic
|
||||
Cryptol.Symbolic.BitVector
|
||||
Cryptol.Symbolic.Prims
|
||||
Cryptol.Symbolic.Value
|
||||
|
||||
|
||||
Other-modules: Cryptol.Parser.LexerUtils,
|
||||
Cryptol.Parser.ParserUtils,
|
||||
Data.SBV,
|
||||
Data.SBV.Bridge.Boolector,
|
||||
Data.SBV.Bridge.CVC4,
|
||||
Data.SBV.Bridge.Yices,
|
||||
Data.SBV.Bridge.Z3,
|
||||
Data.SBV.Internals,
|
||||
Data.SBV.BitVectors.AlgReals,
|
||||
Data.SBV.BitVectors.Data,
|
||||
Data.SBV.BitVectors.Model,
|
||||
Data.SBV.BitVectors.PrettyNum,
|
||||
Data.SBV.BitVectors.SignCast,
|
||||
Data.SBV.BitVectors.Splittable,
|
||||
Data.SBV.BitVectors.STree,
|
||||
Data.SBV.Compilers.C,
|
||||
Data.SBV.Compilers.CodeGen,
|
||||
Data.SBV.SMT.SMT,
|
||||
Data.SBV.SMT.SMTLib,
|
||||
Data.SBV.SMT.SMTLib1,
|
||||
Data.SBV.SMT.SMTLib2,
|
||||
Data.SBV.Provers.Prover,
|
||||
Data.SBV.Provers.SExpr,
|
||||
Data.SBV.Provers.Boolector,
|
||||
Data.SBV.Provers.CVC4,
|
||||
Data.SBV.Provers.Yices,
|
||||
Data.SBV.Provers.Z3,
|
||||
Data.SBV.Tools.ExpectedValue,
|
||||
Data.SBV.Tools.GenTest,
|
||||
Data.SBV.Tools.Optimize,
|
||||
Data.SBV.Tools.Polynomial,
|
||||
Data.SBV.Utils.Boolean,
|
||||
Data.SBV.Utils.TDiff,
|
||||
Data.SBV.Utils.Lib,
|
||||
Paths_cryptol_parser,
|
||||
GitRev
|
||||
|
||||
GHC-options: -Wall -O2
|
||||
|
||||
executable cryptol
|
||||
Main-is: Main.hs
|
||||
hs-source-dirs: cryptol
|
||||
Other-modules: OptParser,
|
||||
REPL.Command,
|
||||
REPL.Haskeline,
|
||||
REPL.Monad,
|
||||
REPL.Trie,
|
||||
Paths_cryptol_parser
|
||||
build-depends: base,
|
||||
ansi-terminal,
|
||||
containers,
|
||||
cryptol-parser,
|
||||
directory,
|
||||
filepath,
|
||||
haskeline,
|
||||
monadLib,
|
||||
process,
|
||||
random,
|
||||
transformers
|
||||
GHC-options: -Wall -O2
|
||||
|
||||
if os(linux) && flag(static)
|
||||
ld-options: -static -pthread
|
||||
|
||||
executable cryptolnb
|
||||
buildable: False
|
||||
Main-is: Main_notebook.hs
|
||||
hs-source-dirs: cryptol, notebook
|
||||
build-depends: base,
|
||||
ansi-terminal,
|
||||
containers,
|
||||
cryptol-parser,
|
||||
directory,
|
||||
filepath,
|
||||
haskeline,
|
||||
monadLib,
|
||||
process,
|
||||
random,
|
||||
transformers
|
||||
GHC-options: -Wall -O2
|
||||
|
||||
if os(linux) && flag(static)
|
||||
ld-options: -static -pthread
|
118
cryptol/Main.hs
Normal file
118
cryptol/Main.hs
Normal file
@ -0,0 +1,118 @@
|
||||
-- |
|
||||
-- Module : $Header$
|
||||
-- Copyright : (c) 2013-2014 Galois, Inc.
|
||||
-- License : BSD3
|
||||
-- Maintainer : cryptol@galois.com
|
||||
-- Stability : provisional
|
||||
-- Portability : portable
|
||||
|
||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||
|
||||
module Main where
|
||||
|
||||
import OptParser
|
||||
import REPL.Command (loadCmd,loadPrelude)
|
||||
import REPL.Haskeline
|
||||
import REPL.Monad (REPL,setREPLTitle,io)
|
||||
import REPL.Logo
|
||||
import qualified REPL.Monad as REPL
|
||||
import Paths_cryptol_parser (version)
|
||||
|
||||
import Cryptol.Version (commitHash, commitBranch, commitDirty)
|
||||
import Data.Version (showVersion)
|
||||
import Cryptol.Utils.PP(pp)
|
||||
import Data.Monoid (mconcat)
|
||||
import System.Environment (getArgs,getProgName)
|
||||
import System.Exit (exitFailure)
|
||||
import System.Console.GetOpt
|
||||
(OptDescr(..),ArgOrder(..),ArgDescr(..),getOpt,usageInfo)
|
||||
|
||||
|
||||
data Options = Options
|
||||
{ optLoad :: [FilePath]
|
||||
, optVersion :: Bool
|
||||
, optHelp :: Bool
|
||||
, optBatch :: Maybe FilePath
|
||||
} deriving (Show)
|
||||
|
||||
defaultOptions :: Options
|
||||
defaultOptions = Options
|
||||
{ optLoad = []
|
||||
, optVersion = False
|
||||
, optHelp = False
|
||||
, optBatch = Nothing
|
||||
}
|
||||
|
||||
options :: [OptDescr (OptParser Options)]
|
||||
options =
|
||||
[ Option "b" ["batch"] (ReqArg setBatchScript "FILE")
|
||||
"run the script provided and exit"
|
||||
|
||||
, Option "v" ["version"] (NoArg setVersion)
|
||||
"display version number"
|
||||
|
||||
, Option "h" ["help"] (NoArg setHelp)
|
||||
"display this message"
|
||||
]
|
||||
|
||||
-- | Set a single file to be loaded. This should be extended in the future, if
|
||||
-- we ever plan to allow multiple files to be loaded at the same time.
|
||||
addFile :: String -> OptParser Options
|
||||
addFile path = modify $ \ opts -> opts { optLoad = [ path ] }
|
||||
|
||||
-- | Set a batch script to be run.
|
||||
setBatchScript :: String -> OptParser Options
|
||||
setBatchScript path = modify $ \ opts -> opts { optBatch = Just path }
|
||||
|
||||
-- | Signal that version should be displayed.
|
||||
setVersion :: OptParser Options
|
||||
setVersion = modify $ \ opts -> opts { optVersion = True }
|
||||
|
||||
-- | Signal that help should be displayed.
|
||||
setHelp :: OptParser Options
|
||||
setHelp = modify $ \ opts -> opts { optHelp = True }
|
||||
|
||||
-- | Parse arguments.
|
||||
parseArgs :: [String] -> Either [String] Options
|
||||
parseArgs args = case getOpt (ReturnInOrder addFile) options args of
|
||||
(ps,[],[]) -> runOptParser defaultOptions (mconcat ps)
|
||||
(_,_,errs) -> Left errs
|
||||
|
||||
displayVersion :: IO ()
|
||||
displayVersion = do
|
||||
let ver = showVersion version
|
||||
putStrLn ("Cryptol " ++ ver)
|
||||
putStrLn ("Git commit " ++ commitHash)
|
||||
putStrLn (" branch " ++ commitBranch ++ dirtyLab)
|
||||
where
|
||||
dirtyLab | commitDirty = " (non-committed files present during build)"
|
||||
| otherwise = ""
|
||||
|
||||
displayHelp :: [String] -> IO ()
|
||||
displayHelp errs = do
|
||||
prog <- getProgName
|
||||
let banner = "Usage: " ++ prog ++ " [OPTIONS]"
|
||||
putStrLn (usageInfo (concat (errs ++ [banner])) options)
|
||||
|
||||
main :: IO ()
|
||||
main = do
|
||||
args <- getArgs
|
||||
case parseArgs args of
|
||||
|
||||
Left errs -> do
|
||||
displayHelp errs
|
||||
exitFailure
|
||||
|
||||
Right opts
|
||||
| optHelp opts -> displayHelp []
|
||||
| optVersion opts -> displayVersion
|
||||
| otherwise -> repl (optBatch opts) (setupREPL opts)
|
||||
|
||||
setupREPL :: Options -> REPL ()
|
||||
setupREPL opts = do
|
||||
displayLogo True
|
||||
setREPLTitle
|
||||
case optLoad opts of
|
||||
[] -> loadPrelude `REPL.catch` \x -> io $ print $ pp x
|
||||
[l] -> loadCmd l `REPL.catch` \x -> io $ print $ pp x
|
||||
_ -> io $ putStrLn "Only one file may be loaded at the command line."
|
35
cryptol/OptParser.hs
Normal file
35
cryptol/OptParser.hs
Normal file
@ -0,0 +1,35 @@
|
||||
-- |
|
||||
-- Module : $Header$
|
||||
-- Copyright : (c) 2013-2014 Galois, Inc.
|
||||
-- License : BSD3
|
||||
-- Maintainer : cryptol@galois.com
|
||||
-- Stability : provisional
|
||||
-- Portability : portable
|
||||
|
||||
|
||||
module OptParser where
|
||||
|
||||
import Data.Monoid (Endo(..),Monoid(..))
|
||||
|
||||
data OptParser opt
|
||||
= OptSuccess (Endo opt)
|
||||
| OptFailure [String]
|
||||
|
||||
instance Monoid (OptParser opt) where
|
||||
mempty = OptSuccess mempty
|
||||
l `mappend` r = case (l,r) of
|
||||
(OptSuccess f,OptSuccess g) -> OptSuccess (f `mappend` g)
|
||||
(OptFailure a,OptFailure b) -> OptFailure (a `mappend` b)
|
||||
(OptFailure _,_) -> l
|
||||
(_,OptFailure _) -> r
|
||||
|
||||
runOptParser :: opt -> OptParser opt -> Either [String] opt
|
||||
runOptParser def parse = case parse of
|
||||
OptSuccess update -> Right (appEndo update def)
|
||||
OptFailure msgs -> Left msgs
|
||||
|
||||
modify :: (opt -> opt) -> OptParser opt
|
||||
modify f = OptSuccess (Endo f)
|
||||
|
||||
report :: String -> OptParser opt
|
||||
report msg = OptFailure [msg]
|
687
cryptol/REPL/Command.hs
Normal file
687
cryptol/REPL/Command.hs
Normal file
@ -0,0 +1,687 @@
|
||||
-- |
|
||||
-- Module : $Header$
|
||||
-- Copyright : (c) 2013-2014 Galois, Inc.
|
||||
-- License : BSD3
|
||||
-- Maintainer : cryptol@galois.com
|
||||
-- Stability : provisional
|
||||
-- Portability : portable
|
||||
|
||||
{-# LANGUAGE CPP, PatternGuards, FlexibleContexts #-}
|
||||
module REPL.Command (
|
||||
-- * Commands
|
||||
Command(..), CommandDescr(..), CommandBody(..)
|
||||
, parseCommand
|
||||
, runCommand
|
||||
, splitCommand
|
||||
, findCommand
|
||||
, findNbCommand
|
||||
|
||||
, moduleCmd, loadCmd, loadPrelude
|
||||
|
||||
-- Misc utilities
|
||||
, handleCtrlC
|
||||
, sanitize
|
||||
|
||||
-- To support Notebook interface (might need to refactor)
|
||||
, replParse
|
||||
, liftModuleCmd
|
||||
, moduleCmdResult
|
||||
) where
|
||||
|
||||
import REPL.Monad
|
||||
import REPL.Trie
|
||||
|
||||
import qualified Cryptol.ModuleSystem as M
|
||||
import qualified Cryptol.ModuleSystem.Base as M (preludeName)
|
||||
|
||||
import qualified Cryptol.Eval.Value as E
|
||||
import qualified Cryptol.Testing.Random as TestR
|
||||
import qualified Cryptol.Testing.Exhaust as TestX
|
||||
import Cryptol.Parser
|
||||
(parseExprWith,ParseError(),Config(..),defaultConfig,parseModName)
|
||||
import Cryptol.Parser.Position (emptyRange,getLoc)
|
||||
import qualified Cryptol.TypeCheck.AST as T
|
||||
import qualified Cryptol.TypeCheck.Subst as T
|
||||
import qualified Cryptol.TypeCheck.InferTypes as T
|
||||
import Cryptol.TypeCheck.PP (dump,ppWithNames)
|
||||
import Cryptol.TypeCheck.Defaulting(defaultExpr)
|
||||
import Cryptol.Utils.PP
|
||||
import Cryptol.Utils.Panic(panic)
|
||||
import qualified Cryptol.Parser.AST as P
|
||||
import Cryptol.Prims.Doc(helpDoc)
|
||||
import qualified Cryptol.Transform.Specialize as S
|
||||
import qualified Cryptol.Symbolic
|
||||
|
||||
import Control.Monad (guard,unless,forM_,when)
|
||||
import Data.Char (isSpace,isPunctuation,isSymbol)
|
||||
import Data.Function (on)
|
||||
import Data.List (intercalate,isPrefixOf)
|
||||
import Data.Maybe (fromMaybe,mapMaybe)
|
||||
import System.Exit (ExitCode(ExitSuccess))
|
||||
import System.Process (shell,createProcess,waitForProcess)
|
||||
import qualified System.Process as Process(runCommand)
|
||||
import System.FilePath((</>), isPathSeparator)
|
||||
import System.Directory(getHomeDirectory,setCurrentDirectory,doesDirectoryExist)
|
||||
import qualified Data.Map as Map
|
||||
import qualified Data.IntMap as IntMap
|
||||
import System.IO(hFlush,stdout)
|
||||
import System.Random(newStdGen)
|
||||
import Numeric (showFFloat)
|
||||
|
||||
#if __GLASGOW_HASKELL__ < 706
|
||||
import Control.Monad (liftM)
|
||||
import qualified Text.ParserCombinators.ReadP as P
|
||||
import Text.Read hiding (step)
|
||||
import System.Environment (getEnvironment)
|
||||
|
||||
lookupEnv :: String -> IO (Maybe String)
|
||||
lookupEnv key = lookup key `liftM` getEnvironment
|
||||
|
||||
readEither :: Read a => String -> Either String a
|
||||
readEither s =
|
||||
case [ x | (x,"") <- readPrec_to_S read' minPrec s ] of
|
||||
[x] -> Right x
|
||||
[] -> Left "Prelude.read: no parse"
|
||||
_ -> Left "Prelude.read: ambiguous parse"
|
||||
where
|
||||
read' =
|
||||
do x <- readPrec
|
||||
lift P.skipSpaces
|
||||
return x
|
||||
|
||||
-- | Parse a string using the 'Read' instance.
|
||||
-- Succeeds if there is exactly one valid result.
|
||||
readMaybe :: Read a => String -> Maybe a
|
||||
readMaybe s = case readEither s of
|
||||
Left _ -> Nothing
|
||||
Right a -> Just a
|
||||
#else
|
||||
import System.Environment (lookupEnv)
|
||||
#endif
|
||||
|
||||
-- Commands --------------------------------------------------------------------
|
||||
|
||||
-- | Commands.
|
||||
data Command
|
||||
= Command (REPL ()) -- ^ Successfully parsed command
|
||||
| Ambiguous String [String] -- ^ Ambiguous command, list of conflicting
|
||||
-- commands
|
||||
| Unknown String -- ^ The unknown command
|
||||
|
||||
-- | Command builder.
|
||||
data CommandDescr = CommandDescr
|
||||
{ cName :: String
|
||||
, cBody :: CommandBody
|
||||
, cHelp :: String
|
||||
}
|
||||
|
||||
instance Show CommandDescr where
|
||||
show = cName
|
||||
|
||||
instance Eq CommandDescr where
|
||||
(==) = (==) `on` cName
|
||||
|
||||
instance Ord CommandDescr where
|
||||
compare = compare `on` cName
|
||||
|
||||
data CommandBody
|
||||
= ExprArg (String -> REPL ())
|
||||
| ExprTypeArg (String -> REPL ())
|
||||
| FilenameArg (FilePath -> REPL ())
|
||||
| OptionArg (String -> REPL ())
|
||||
| ShellArg (String -> REPL ())
|
||||
| NoArg (REPL ())
|
||||
|
||||
|
||||
-- | REPL command parsing.
|
||||
commands :: CommandMap
|
||||
commands = foldl insert emptyTrie commandList
|
||||
where
|
||||
insert m d = insertTrie (cName d) d m
|
||||
|
||||
-- | Notebook command parsing.
|
||||
nbCommands :: CommandMap
|
||||
nbCommands = foldl insert emptyTrie nbCommandList
|
||||
where
|
||||
insert m d = insertTrie (cName d) d m
|
||||
|
||||
-- | A subset of commands safe for Notebook execution
|
||||
nbCommandList :: [CommandDescr]
|
||||
nbCommandList =
|
||||
[ CommandDescr ":type" (ExprArg typeOfCmd)
|
||||
"check the type of an expression"
|
||||
, CommandDescr ":browse" (ExprTypeArg browseCmd)
|
||||
"display the current environment"
|
||||
, CommandDescr ":help" (ExprArg helpCmd)
|
||||
"display a brief description about a built-in operator"
|
||||
, CommandDescr ":set" (OptionArg setOptionCmd)
|
||||
"set an environmental option (:set on its own displays current values)"
|
||||
]
|
||||
|
||||
commandList :: [CommandDescr]
|
||||
commandList =
|
||||
nbCommandList ++
|
||||
[ CommandDescr ":quit" (NoArg quitCmd)
|
||||
"exit the REPL"
|
||||
, CommandDescr ":load" (FilenameArg loadCmd)
|
||||
"load a module"
|
||||
, CommandDescr ":reload" (NoArg reloadCmd)
|
||||
"reload the currently loaded module"
|
||||
, CommandDescr ":edit" (FilenameArg editCmd)
|
||||
"edit the currently loaded module"
|
||||
, CommandDescr ":!" (ShellArg runShellCmd)
|
||||
"execute a command in the shell"
|
||||
, CommandDescr ":cd" (FilenameArg cdCmd)
|
||||
"set the current working directory"
|
||||
, CommandDescr ":module" (FilenameArg moduleCmd)
|
||||
"load a module"
|
||||
|
||||
, CommandDescr ":check" (ExprArg qcCmd)
|
||||
"use random testing to check that the argument always returns true"
|
||||
, CommandDescr ":prove" (ExprArg proveCmd)
|
||||
"use an external solver to prove that the argument always returns true"
|
||||
, CommandDescr ":sat" (ExprArg satCmd)
|
||||
"use a solver to find a satisfying assignment for which the argument returns true"
|
||||
, CommandDescr ":debug_specialize" (ExprArg specializeCmd)
|
||||
"do type specialization on a closed expression"
|
||||
]
|
||||
|
||||
genHelp :: [CommandDescr] -> [String]
|
||||
genHelp cs = map cmdHelp cs
|
||||
where
|
||||
cmdHelp cmd = concat [ " ", cName cmd, pad (cName cmd), cHelp cmd ]
|
||||
padding = 2 + maximum (map (length . cName) cs)
|
||||
pad n = replicate (max 0 (padding - length n)) ' '
|
||||
|
||||
|
||||
-- Command Evaluation ----------------------------------------------------------
|
||||
|
||||
-- | Run a command.
|
||||
runCommand :: Command -> REPL ()
|
||||
runCommand c = case c of
|
||||
|
||||
Command cmd -> cmd `REPL.Monad.catch` handler
|
||||
where
|
||||
handler re = io (putStrLn "" >> print (pp re))
|
||||
|
||||
Unknown cmd -> io (putStrLn ("Unknown command: " ++ cmd))
|
||||
|
||||
Ambiguous cmd cmds -> io $ do
|
||||
putStrLn (cmd ++ " is ambiguous, it could mean one of:")
|
||||
putStrLn ("\t" ++ intercalate ", " cmds)
|
||||
|
||||
|
||||
-- Get the setting we should use for displaying values.
|
||||
getPPValOpts :: REPL E.PPOpts
|
||||
getPPValOpts =
|
||||
do EnvNum base <- getUser "base"
|
||||
EnvBool ascii <- getUser "ascii"
|
||||
EnvNum infLength <- getUser "infLength"
|
||||
return E.PPOpts { E.useBase = base
|
||||
, E.useAscii = ascii
|
||||
, E.useInfLength = infLength
|
||||
}
|
||||
|
||||
evalCmd :: String -> REPL ()
|
||||
evalCmd str = do
|
||||
(val,_ty) <- replEvalExpr str
|
||||
ppOpts <- getPPValOpts
|
||||
io $ rethrowEvalError $ print $ pp $ E.WithBase ppOpts val
|
||||
|
||||
qcCmd :: String -> REPL ()
|
||||
qcCmd "" =
|
||||
do xs <- getPropertyNames
|
||||
if null xs
|
||||
then io $ putStrLn "There are no properties in scope."
|
||||
else forM_ xs $ \x ->
|
||||
do io $ putStr $ "property " ++ x ++ " "
|
||||
qcCmd x
|
||||
|
||||
qcCmd str =
|
||||
do (val,ty) <- replEvalExpr str
|
||||
EnvNum testNum <- getUser "tests"
|
||||
case TestX.testableType ty of
|
||||
Just (sz,vss) | sz <= toInteger testNum ->
|
||||
do io $ putStrLn "Using exhaustive testing."
|
||||
let doTest _ [] = panic "We've unexpectedly run out of test cases"
|
||||
[]
|
||||
doTest _ (vs : vss1) =
|
||||
if TestX.runTest val vs
|
||||
then (Nothing, vss1)
|
||||
else (Just vs, vss1)
|
||||
ok <- go doTest sz 0 vss
|
||||
when ok $ io $ putStrLn "QED"
|
||||
|
||||
n -> case TestR.testableType ty of
|
||||
Nothing -> raise (TypeNotTestable ty)
|
||||
Just gens ->
|
||||
do io $ putStrLn "Using random testing."
|
||||
prt testingMsg
|
||||
g <- io newStdGen
|
||||
ok <- go (TestR.runTest val gens) testNum 0 g
|
||||
when ok $
|
||||
case n of
|
||||
Just (valNum,_) ->
|
||||
do let valNumD = fromIntegral valNum :: Double
|
||||
percent = fromIntegral (testNum * 100)
|
||||
/ valNumD
|
||||
showValNum
|
||||
| valNum > 2 ^ (20::Integer) =
|
||||
"2^^" ++ show (round $ logBase 2 valNumD :: Integer)
|
||||
| otherwise = show valNum
|
||||
io $ putStrLn $ "Coverage: "
|
||||
++ showFFloat (Just 2) percent "% ("
|
||||
++ show testNum ++ " of "
|
||||
++ showValNum ++ " values)"
|
||||
Nothing -> return ()
|
||||
|
||||
where
|
||||
testingMsg = "testing..."
|
||||
|
||||
totProgressWidth = 4 -- 100%
|
||||
|
||||
prt msg = io (putStr msg >> hFlush stdout)
|
||||
prtLn msg = io (putStrLn msg >> hFlush stdout)
|
||||
|
||||
ppProgress this tot =
|
||||
let percent = show (div (100 * this) tot) ++ "%"
|
||||
width = length percent
|
||||
pad = replicate (totProgressWidth - width) ' '
|
||||
in prt (pad ++ percent)
|
||||
|
||||
del n = prt (replicate n '\BS')
|
||||
delTesting = del (length testingMsg)
|
||||
delProgress = del totProgressWidth
|
||||
|
||||
go _ totNum testNum _
|
||||
| testNum >= totNum =
|
||||
do delTesting
|
||||
prtLn $ "passed " ++ show totNum ++ " tests."
|
||||
return True
|
||||
|
||||
go doTest totNum testNum st =
|
||||
do ppProgress testNum totNum
|
||||
case doTest (div (100 * (1 + testNum)) totNum) st of
|
||||
(Nothing, st1) -> do delProgress
|
||||
go doTest totNum (testNum + 1) st1
|
||||
(Just vs, _g1) ->
|
||||
do opts <- getPPValOpts
|
||||
do delProgress
|
||||
delTesting
|
||||
prtLn "FAILED for the following inputs:"
|
||||
io $ mapM_ (print . pp . E.WithBase opts) vs
|
||||
return False
|
||||
|
||||
|
||||
proveCmd :: String -> REPL ()
|
||||
proveCmd str = do
|
||||
parseExpr <- replParseExpr str
|
||||
(expr, schema) <- replCheckExpr parseExpr
|
||||
-- spexpr <- replSpecExpr expr
|
||||
EnvString proverName <- getUser "prover"
|
||||
EnvBool iteSolver <- getUser "iteSolver"
|
||||
EnvBool verbose <- getUser "debug"
|
||||
liftModuleCmd $ Cryptol.Symbolic.prove (proverName, iteSolver, verbose, str) (expr, schema)
|
||||
|
||||
satCmd :: String -> REPL ()
|
||||
satCmd str = do
|
||||
parseExpr <- replParseExpr str
|
||||
(expr, schema) <- replCheckExpr parseExpr
|
||||
EnvString proverName <- getUser "prover"
|
||||
EnvBool iteSolver <- getUser "iteSolver"
|
||||
EnvBool verbose <- getUser "debug"
|
||||
liftModuleCmd $ Cryptol.Symbolic.sat (proverName, iteSolver, verbose, str) (expr, schema)
|
||||
|
||||
specializeCmd :: String -> REPL ()
|
||||
specializeCmd str = do
|
||||
parseExpr <- replParseExpr str
|
||||
(expr, schema) <- replCheckExpr parseExpr
|
||||
spexpr <- replSpecExpr expr
|
||||
io $ putStrLn "Expression type:"
|
||||
io $ print $ pp schema
|
||||
io $ putStrLn "Original expression:"
|
||||
io $ putStrLn $ dump expr
|
||||
io $ putStrLn "Specialized expression:"
|
||||
io $ putStrLn $ dump spexpr
|
||||
|
||||
typeOfCmd :: String -> REPL ()
|
||||
typeOfCmd str = do
|
||||
expr <- replParseExpr str
|
||||
(def,sig) <- replCheckExpr expr
|
||||
|
||||
-- XXX need more warnings from the module system
|
||||
--io (mapM_ printWarning ws)
|
||||
whenDebug (io (putStrLn (dump def)))
|
||||
io $ print $ pp expr <+> text ":" <+> pp sig
|
||||
|
||||
reloadCmd :: REPL ()
|
||||
reloadCmd = do
|
||||
mb <- getLoadedMod
|
||||
case mb of
|
||||
Just m -> loadCmd (lPath m)
|
||||
Nothing -> return ()
|
||||
|
||||
|
||||
editCmd :: String -> REPL ()
|
||||
editCmd path
|
||||
| null path = do
|
||||
mb <- getLoadedMod
|
||||
case mb of
|
||||
|
||||
Just m -> do
|
||||
success <- replEdit (lPath m)
|
||||
if success
|
||||
then loadCmd (lPath m)
|
||||
else return ()
|
||||
|
||||
Nothing -> do
|
||||
io (putStrLn "No files to edit.")
|
||||
return ()
|
||||
|
||||
| otherwise = do
|
||||
_ <- replEdit path
|
||||
mb <- getLoadedMod
|
||||
case mb of
|
||||
Nothing -> loadCmd path
|
||||
Just _ -> return ()
|
||||
|
||||
moduleCmd :: String -> REPL ()
|
||||
moduleCmd modString
|
||||
| null modString = return ()
|
||||
| otherwise = do
|
||||
case parseModName modString of
|
||||
Just m -> loadCmd =<< liftModuleCmd (M.findModule m)
|
||||
Nothing -> io $ putStrLn "Invalid module name."
|
||||
|
||||
loadPrelude :: REPL ()
|
||||
loadPrelude = moduleCmd $ show $ pp M.preludeName
|
||||
|
||||
loadCmd :: FilePath -> REPL ()
|
||||
loadCmd path
|
||||
| null path = return ()
|
||||
| otherwise = do
|
||||
setLoadedMod LoadedModule
|
||||
{ lName = Nothing
|
||||
, lPath = path
|
||||
}
|
||||
|
||||
m <- moduleCmdResult =<< io (M.loadModuleByPath path)
|
||||
whenDebug (io (putStrLn (dump m)))
|
||||
setLoadedMod LoadedModule
|
||||
{ lName = Just (T.mName m)
|
||||
, lPath = path
|
||||
}
|
||||
|
||||
quitCmd :: REPL ()
|
||||
quitCmd = stop
|
||||
|
||||
|
||||
browseCmd :: String -> REPL ()
|
||||
browseCmd pfx = do
|
||||
browseTSyns pfx
|
||||
browseNewtypes pfx
|
||||
browseVars pfx
|
||||
|
||||
browseTSyns :: String -> REPL ()
|
||||
browseTSyns pfx = do
|
||||
tsyns <- getTSyns
|
||||
let tsyns' = Map.filterWithKey (\k _ -> pfx `isNamePrefix` k) tsyns
|
||||
unless (Map.null tsyns') $ io $ do
|
||||
putStrLn "Type Synonyms"
|
||||
putStrLn "============="
|
||||
let ppSyn (qn,T.TySyn _ ps cs ty) = pp (T.TySyn qn ps cs ty)
|
||||
print (nest 4 (vcat (map ppSyn (Map.toList tsyns'))))
|
||||
putStrLn ""
|
||||
|
||||
browseNewtypes :: String -> REPL ()
|
||||
browseNewtypes pfx = do
|
||||
nts <- getNewtypes
|
||||
let nts' = Map.filterWithKey (\k _ -> pfx `isNamePrefix` k) nts
|
||||
unless (Map.null nts') $ io $ do
|
||||
putStrLn "Newtypes"
|
||||
putStrLn "========"
|
||||
let ppNT (qn,nt) = T.ppNewtypeShort (nt { T.ntName = qn })
|
||||
print (nest 4 (vcat (map ppNT (Map.toList nts'))))
|
||||
putStrLn ""
|
||||
|
||||
browseVars :: String -> REPL ()
|
||||
browseVars pfx = do
|
||||
vars <- getVars
|
||||
let allNames = vars
|
||||
{- This shows the built-ins as well:
|
||||
Map.union vars
|
||||
(Map.fromList [ (Name x,t) | (x,(_,t)) <- builtIns ]) -}
|
||||
vars' = Map.filterWithKey (\k _ -> pfx `isNamePrefix` k) allNames
|
||||
|
||||
isProp p = T.PragmaProperty `elem` (M.ifDeclPragmas p)
|
||||
(props,syms) = Map.partition isProp vars'
|
||||
|
||||
ppBlock "Properties" props
|
||||
ppBlock "Symbols" syms
|
||||
|
||||
where
|
||||
ppBlock name xs =
|
||||
unless (Map.null xs) $ io $ do
|
||||
putStrLn name
|
||||
putStrLn (replicate (length name) '=')
|
||||
let step k d acc =
|
||||
pp k <+> char ':' <+> pp (M.ifDeclSig d) : acc
|
||||
print (nest 4 (vcat (Map.foldrWithKey step [] xs)))
|
||||
putStrLn ""
|
||||
|
||||
|
||||
|
||||
setOptionCmd :: String -> REPL ()
|
||||
setOptionCmd str
|
||||
| Just value <- mbValue = setUser (mkKey key) value
|
||||
| null key = mapM_ (describe . optName) (leaves userOptions)
|
||||
| otherwise = describe key
|
||||
where
|
||||
(before,after) = break (== '=') str
|
||||
key = trim before
|
||||
mbValue = case after of
|
||||
_ : stuff -> Just (trim stuff)
|
||||
_ -> Nothing
|
||||
|
||||
|
||||
|
||||
mkKey = takeWhile (not . isSpace)
|
||||
|
||||
describe k = do
|
||||
ev <- tryGetUser (mkKey k)
|
||||
io $ case ev of
|
||||
Just (EnvString s) -> putStrLn (k ++ " = " ++ s)
|
||||
Just (EnvNum n) -> putStrLn (k ++ " = " ++ show n)
|
||||
Just (EnvBool True) -> putStrLn (k ++ " = on")
|
||||
Just (EnvBool False) -> putStrLn (k ++ " = off")
|
||||
Nothing -> putStrLn ("Unknown user option: `" ++ k ++ "`")
|
||||
|
||||
|
||||
helpCmd :: String -> REPL ()
|
||||
helpCmd cmd
|
||||
| null cmd = io (mapM_ putStrLn (genHelp commandList))
|
||||
| Just (ec,_) <- lookup cmd builtIns =
|
||||
io $ print $ helpDoc ec
|
||||
| otherwise = do io $ putStrLn $ "// No documentation is available."
|
||||
typeOfCmd cmd
|
||||
|
||||
|
||||
runShellCmd :: String -> REPL ()
|
||||
runShellCmd cmd
|
||||
= io $ do h <- Process.runCommand cmd
|
||||
_ <- waitForProcess h
|
||||
return ()
|
||||
|
||||
cdCmd :: FilePath -> REPL ()
|
||||
cdCmd f | null f = io $ putStrLn $ "[error] :cd requires a path argument"
|
||||
| otherwise = do
|
||||
exists <- io $ doesDirectoryExist f
|
||||
if exists
|
||||
then io $ setCurrentDirectory f
|
||||
else raise $ DirectoryNotFound f
|
||||
|
||||
-- C-c Handlings ---------------------------------------------------------------
|
||||
|
||||
-- XXX this should probably do something a bit more specific.
|
||||
handleCtrlC :: REPL ()
|
||||
handleCtrlC = io (putStrLn "Ctrl-C")
|
||||
|
||||
|
||||
-- Utilities -------------------------------------------------------------------
|
||||
|
||||
isNamePrefix :: String -> P.QName -> Bool
|
||||
isNamePrefix pfx n = case n of
|
||||
P.QName _ (P.Name _) -> pfx `isPrefixOf` pretty n
|
||||
_ -> False
|
||||
|
||||
{-
|
||||
printWarning :: (Range,Warning) -> IO ()
|
||||
printWarning = print . ppWarning
|
||||
|
||||
printError :: (Range,Error) -> IO ()
|
||||
printError = print . ppError
|
||||
-}
|
||||
|
||||
-- | Lift a parsing action into the REPL monad.
|
||||
replParse :: (String -> Either ParseError a) -> String -> REPL a
|
||||
replParse parse str = case parse str of
|
||||
Right a -> return a
|
||||
Left e -> raise (ParseError e)
|
||||
|
||||
replParseExpr :: String -> REPL P.Expr
|
||||
replParseExpr = replParse $ parseExprWith interactiveConfig
|
||||
|
||||
interactiveConfig :: Config
|
||||
interactiveConfig = defaultConfig { cfgSource = "<interactive>" }
|
||||
|
||||
liftModuleCmd :: M.ModuleCmd a -> REPL a
|
||||
liftModuleCmd cmd = moduleCmdResult =<< io . cmd =<< getModuleEnv
|
||||
|
||||
moduleCmdResult :: M.ModuleRes a -> REPL a
|
||||
moduleCmdResult (res,ws0) = do
|
||||
EnvBool yes <- getUser "warnDefaulting"
|
||||
let isDefaultWarn (T.DefaultingTo _ _) = True
|
||||
isDefaultWarn _ = False
|
||||
|
||||
filterDefaults (M.TypeCheckWarnings xs) =
|
||||
case filter (not . isDefaultWarn . snd) xs of
|
||||
[] -> Nothing
|
||||
ys -> Just (M.TypeCheckWarnings ys)
|
||||
filterDefaults w = Just w
|
||||
|
||||
let ws = if yes then ws0
|
||||
else mapMaybe filterDefaults ws0
|
||||
io (mapM_ (print . pp) ws)
|
||||
case res of
|
||||
Right (a,me') -> setModuleEnv me' >> return a
|
||||
Left err -> raise (ModuleSystemError err)
|
||||
|
||||
replCheckExpr :: P.Expr -> REPL (T.Expr,T.Schema)
|
||||
replCheckExpr e = liftModuleCmd $ M.checkExpr e
|
||||
|
||||
replSpecExpr :: T.Expr -> REPL T.Expr
|
||||
replSpecExpr e = liftModuleCmd $ S.specialize e
|
||||
|
||||
replEvalExpr :: String -> REPL (E.Value, T.Type)
|
||||
replEvalExpr str =
|
||||
do expr <- replParseExpr str
|
||||
(def,sig) <- replCheckExpr expr
|
||||
|
||||
let range = fromMaybe emptyRange (getLoc expr)
|
||||
(def1,ty) <-
|
||||
case defaultExpr range def sig of
|
||||
Nothing -> raise (EvalPolyError sig)
|
||||
Just (tys,def1) ->
|
||||
do let nms = T.addTNames (T.sVars sig) IntMap.empty
|
||||
io $ mapM_ (warnDefault nms) tys
|
||||
let su = T.listSubst [ (T.tpVar a, t) | (a,t) <- tys ]
|
||||
return (def1, T.apSubst su (T.sType sig))
|
||||
|
||||
val <- liftModuleCmd (M.evalExpr def1)
|
||||
whenDebug (io (putStrLn (dump def1)))
|
||||
return (val,ty)
|
||||
where
|
||||
warnDefault ns (x,t) =
|
||||
print $ text "Assuming" <+> ppWithNames ns x <+> text "=" <+> pp t
|
||||
|
||||
replEdit :: String -> REPL Bool
|
||||
replEdit file = do
|
||||
mb <- io (lookupEnv "EDITOR")
|
||||
let editor = fromMaybe "vim" mb
|
||||
io $ do
|
||||
(_,_,_,ph) <- createProcess (shell (unwords [editor, file]))
|
||||
exit <- waitForProcess ph
|
||||
return (exit == ExitSuccess)
|
||||
|
||||
type CommandMap = Trie CommandDescr
|
||||
|
||||
|
||||
-- Command Parsing -------------------------------------------------------------
|
||||
|
||||
-- | Strip leading space.
|
||||
sanitize :: String -> String
|
||||
sanitize = dropWhile isSpace
|
||||
|
||||
-- | Strip trailing space.
|
||||
sanitizeEnd :: String -> String
|
||||
sanitizeEnd = reverse . sanitize . reverse
|
||||
|
||||
trim :: String -> String
|
||||
trim = sanitizeEnd . sanitize
|
||||
|
||||
-- | Split at the first word boundary.
|
||||
splitCommand :: String -> Maybe (String,String)
|
||||
splitCommand txt =
|
||||
case sanitize txt of
|
||||
':' : more
|
||||
| (as,bs) <- span (\x -> isPunctuation x || isSymbol x) more
|
||||
, not (null as) -> Just (':' : as, sanitize bs)
|
||||
|
||||
| (as,bs) <- break isSpace more
|
||||
, not (null as) -> Just (':' : as, sanitize bs)
|
||||
|
||||
| otherwise -> Nothing
|
||||
|
||||
expr -> guard (not (null expr)) >> return (expr,[])
|
||||
|
||||
-- | Uncons a list.
|
||||
uncons :: [a] -> Maybe (a,[a])
|
||||
uncons as = case as of
|
||||
a:rest -> Just (a,rest)
|
||||
_ -> Nothing
|
||||
|
||||
-- | Lookup a string in the command list.
|
||||
findCommand :: String -> [CommandDescr]
|
||||
findCommand str = lookupTrie str commands
|
||||
|
||||
-- | Lookup a string in the notebook-safe command list.
|
||||
findNbCommand :: String -> [CommandDescr]
|
||||
findNbCommand str = lookupTrie str nbCommands
|
||||
|
||||
-- | Parse a line as a command.
|
||||
parseCommand :: (String -> [CommandDescr]) -> String -> Maybe Command
|
||||
parseCommand findCmd line = do
|
||||
(cmd,args) <- splitCommand line
|
||||
let args' = sanitizeEnd args
|
||||
case findCmd cmd of
|
||||
[c] -> case cBody c of
|
||||
ExprArg body -> Just (Command (body args'))
|
||||
ExprTypeArg body -> Just (Command (body args'))
|
||||
FilenameArg body -> Just (Command (body =<< expandHome args'))
|
||||
OptionArg body -> Just (Command (body args'))
|
||||
ShellArg body -> Just (Command (body args'))
|
||||
NoArg body -> Just (Command body)
|
||||
|
||||
[] -> case uncons cmd of
|
||||
Just (':',_) -> Just (Unknown cmd)
|
||||
Just _ -> Just (Command (evalCmd line))
|
||||
_ -> Nothing
|
||||
|
||||
cs -> Just (Ambiguous cmd (map cName cs))
|
||||
|
||||
where
|
||||
expandHome path =
|
||||
case path of
|
||||
'~' : c : more | isPathSeparator c -> do dir <- io getHomeDirectory
|
||||
return (dir </> more)
|
||||
_ -> return path
|
190
cryptol/REPL/Haskeline.hs
Normal file
190
cryptol/REPL/Haskeline.hs
Normal file
@ -0,0 +1,190 @@
|
||||
-- |
|
||||
-- Module : $Header$
|
||||
-- Copyright : (c) 2013-2014 Galois, Inc.
|
||||
-- License : BSD3
|
||||
-- Maintainer : cryptol@galois.com
|
||||
-- Stability : provisional
|
||||
-- Portability : portable
|
||||
|
||||
{-# LANGUAGE PatternGuards #-}
|
||||
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||
|
||||
module REPL.Haskeline where
|
||||
|
||||
import REPL.Command
|
||||
import REPL.Monad
|
||||
import REPL.Trie
|
||||
|
||||
import Control.Monad (when)
|
||||
import Data.Char (isSpace)
|
||||
import Data.Function (on)
|
||||
import Data.List (isPrefixOf,sortBy)
|
||||
import System.Console.Haskeline
|
||||
import System.Directory(getAppUserDataDirectory,createDirectoryIfMissing)
|
||||
import System.FilePath((</>))
|
||||
import qualified Control.Monad.IO.Class as MTL
|
||||
import qualified Control.Monad.Trans.Class as MTL
|
||||
import qualified Control.Exception as X
|
||||
|
||||
|
||||
-- | Haskeline-specific repl implementation.
|
||||
--
|
||||
-- XXX this needs to handle Ctrl-C, which at the moment will just cause
|
||||
-- haskeline to exit. See the function 'withInterrupt' for more info on how to
|
||||
-- handle this.
|
||||
repl :: Maybe FilePath -> REPL () -> IO ()
|
||||
repl mbBatch begin =
|
||||
do settings <- setHistoryFile replSettings
|
||||
runREPL isBatch (runInputTBehavior style settings body)
|
||||
where
|
||||
body = withInterrupt $ do
|
||||
MTL.lift begin
|
||||
loop
|
||||
|
||||
(isBatch,style) = case mbBatch of
|
||||
Nothing -> (False,defaultBehavior)
|
||||
Just path -> (True,useFile path)
|
||||
|
||||
loop = do
|
||||
prompt <- MTL.lift getPrompt
|
||||
mb <- handleInterrupt (return (Just "")) (getInputLines prompt [])
|
||||
case mb of
|
||||
|
||||
Just line
|
||||
| Just cmd <- parseCommand findCommand line -> do
|
||||
continue <- MTL.lift $ do
|
||||
handleInterrupt handleCtrlC (runCommand cmd)
|
||||
shouldContinue
|
||||
when continue loop
|
||||
|
||||
| otherwise -> loop
|
||||
|
||||
Nothing -> return ()
|
||||
|
||||
getInputLines prompt ls =
|
||||
do mb <- getInputLine prompt
|
||||
let newPropmpt = map (\_ -> ' ') prompt
|
||||
case mb of
|
||||
Nothing -> return Nothing
|
||||
Just l | not (null l) && last l == '\\' ->
|
||||
getInputLines newPropmpt (init l : ls)
|
||||
| otherwise -> return $ Just $ unlines $ reverse $ l : ls
|
||||
|
||||
|
||||
|
||||
-- | Try to set the history file.
|
||||
setHistoryFile :: Settings REPL -> IO (Settings REPL)
|
||||
setHistoryFile ss =
|
||||
do dir <- getAppUserDataDirectory "cryptol"
|
||||
createDirectoryIfMissing True dir
|
||||
return ss { historyFile = Just (dir </> "history") }
|
||||
`X.catch` \(SomeException {}) -> return ss
|
||||
|
||||
-- | Haskeline settings for the REPL.
|
||||
replSettings :: Settings REPL
|
||||
replSettings = Settings
|
||||
{ complete = cryptolCommand
|
||||
, historyFile = Nothing
|
||||
, autoAddHistory = True
|
||||
}
|
||||
|
||||
|
||||
-- Utilities -------------------------------------------------------------------
|
||||
|
||||
instance MTL.MonadIO REPL where
|
||||
liftIO = io
|
||||
|
||||
instance MonadException REPL where
|
||||
controlIO branchIO = REPL $ \ ref -> do
|
||||
runBody <- branchIO $ RunIO $ \ m -> do
|
||||
a <- unREPL m ref
|
||||
return (return a)
|
||||
unREPL runBody ref
|
||||
|
||||
|
||||
-- Completion ------------------------------------------------------------------
|
||||
|
||||
-- | Completion for cryptol commands.
|
||||
cryptolCommand :: CompletionFunc REPL
|
||||
cryptolCommand cursor@(l,r)
|
||||
| ":" `isPrefixOf` l'
|
||||
, Just (cmd,rest) <- splitCommand l' = case findCommand cmd of
|
||||
|
||||
[c] | null rest && not (any isSpace l') -> do
|
||||
return (l, [cmdComp cmd c])
|
||||
| otherwise -> do
|
||||
(rest',cs) <- cmdArgument (cBody c) (reverse (sanitize rest),r)
|
||||
return (unwords [rest', reverse cmd],cs)
|
||||
|
||||
cmds ->
|
||||
return (l, [ cmdComp l' c | c <- cmds ])
|
||||
|
||||
| otherwise = completeExpr cursor
|
||||
where
|
||||
l' = sanitize (reverse l)
|
||||
|
||||
-- | Generate a completion from a REPL command definition.
|
||||
cmdComp :: String -> CommandDescr -> Completion
|
||||
cmdComp prefix c = Completion
|
||||
{ replacement = drop (length prefix) (cName c)
|
||||
, display = cName c
|
||||
, isFinished = True
|
||||
}
|
||||
|
||||
-- | Dispatch to a completion function based on the kind of completion the
|
||||
-- command is expecting.
|
||||
cmdArgument :: CommandBody -> CompletionFunc REPL
|
||||
cmdArgument ct cursor@(l,_) = case ct of
|
||||
ExprArg _ -> completeExpr cursor
|
||||
ExprTypeArg _ -> (completeExpr +++ completeType) cursor
|
||||
FilenameArg _ -> completeFilename cursor
|
||||
ShellArg _ -> completeFilename cursor
|
||||
OptionArg _ -> completeOption cursor
|
||||
NoArg _ -> return (l,[])
|
||||
|
||||
-- | Complete a name from the expression environment.
|
||||
completeExpr :: CompletionFunc REPL
|
||||
completeExpr (l,_) = do
|
||||
ns <- getExprNames
|
||||
let n = reverse l
|
||||
vars = filter (n `isPrefixOf`) ns
|
||||
return (l,map (nameComp n) vars)
|
||||
|
||||
-- | Complete a name from the type synonym environment.
|
||||
completeType :: CompletionFunc REPL
|
||||
completeType (l,_) = do
|
||||
ns <- getTypeNames
|
||||
let n = reverse l
|
||||
vars = filter (n `isPrefixOf`) ns
|
||||
return (l,map (nameComp n) vars)
|
||||
|
||||
-- | Generate a completion from a prefix and a name.
|
||||
nameComp :: String -> String -> Completion
|
||||
nameComp prefix c = Completion
|
||||
{ replacement = drop (length prefix) c
|
||||
, display = c
|
||||
, isFinished = True
|
||||
}
|
||||
|
||||
|
||||
-- | Join two completion functions together, merging and sorting their results.
|
||||
(+++) :: CompletionFunc REPL -> CompletionFunc REPL -> CompletionFunc REPL
|
||||
(as +++ bs) cursor = do
|
||||
(_,acs) <- as cursor
|
||||
(_,bcs) <- bs cursor
|
||||
return (fst cursor, sortBy (compare `on` replacement) (acs ++ bcs))
|
||||
|
||||
|
||||
-- | Complete an option from the options environment.
|
||||
--
|
||||
-- XXX this can do better, as it has access to the expected form of the value
|
||||
completeOption :: CompletionFunc REPL
|
||||
completeOption cursor@(l,_) = return (fst cursor, map comp opts)
|
||||
where
|
||||
n = reverse l
|
||||
opts = lookupTrie n userOptions
|
||||
comp opt = Completion
|
||||
{ replacement = drop (length n) (optName opt)
|
||||
, display = optName opt
|
||||
, isFinished = False
|
||||
}
|
52
cryptol/REPL/Logo.hs
Normal file
52
cryptol/REPL/Logo.hs
Normal file
@ -0,0 +1,52 @@
|
||||
-- |
|
||||
-- Module : $Header$
|
||||
-- Copyright : (c) 2013-2014 Galois, Inc.
|
||||
-- License : BSD3
|
||||
-- Maintainer : cryptol@galois.com
|
||||
-- Stability : provisional
|
||||
-- Portability : portable
|
||||
|
||||
module REPL.Logo where
|
||||
|
||||
import REPL.Monad
|
||||
import Paths_cryptol_parser (version)
|
||||
|
||||
import Cryptol.Version (commitShortHash)
|
||||
import Data.Version (showVersion)
|
||||
import System.Console.ANSI
|
||||
|
||||
|
||||
type Version = String
|
||||
|
||||
type Logo = [String]
|
||||
|
||||
logo :: Bool -> Logo
|
||||
logo useColor =
|
||||
[ sgr [SetColor Foreground Dull White] ++ l | l <- ws ]
|
||||
++ [ sgr [SetColor Foreground Vivid Blue ] ++ l | l <- vs ]
|
||||
++ [ sgr [SetColor Foreground Dull Blue ] ++ l | l <- ds ]
|
||||
++ [ sgr [Reset] ]
|
||||
where
|
||||
sgr | useColor = setSGRCode
|
||||
| otherwise = const []
|
||||
hashText | commitShortHash == "UNKNOWN" = ""
|
||||
| otherwise = " (" ++ commitShortHash ++ ")"
|
||||
versionText = "version " ++ showVersion version ++ hashText
|
||||
ver = sgr [SetColor Foreground Dull White]
|
||||
++ replicate (lineLen - 20 - length versionText) ' '
|
||||
++ versionText
|
||||
ls =
|
||||
[ " _ _"
|
||||
, " ___ _ __ _ _ _ __ | |_ ___ | |"
|
||||
, " / __| \'__| | | | \'_ \\| __/ _ \\| |"
|
||||
, " | (__| | | |_| | |_) | || (_) | |"
|
||||
, " \\___|_| \\__, | .__/ \\__\\___/|_|"
|
||||
, " |___/|_| " ++ ver
|
||||
]
|
||||
slen = length ls `div` 3
|
||||
(ws,rest) = splitAt slen ls
|
||||
(vs,ds) = splitAt slen rest
|
||||
lineLen = length (head ls)
|
||||
|
||||
displayLogo :: Bool -> REPL ()
|
||||
displayLogo useColor =unlessBatch (io (mapM_ putStrLn (logo useColor)))
|
420
cryptol/REPL/Monad.hs
Normal file
420
cryptol/REPL/Monad.hs
Normal file
@ -0,0 +1,420 @@
|
||||
-- |
|
||||
-- Module : $Header$
|
||||
-- Copyright : (c) 2013-2014 Galois, Inc.
|
||||
-- License : BSD3
|
||||
-- Maintainer : cryptol@galois.com
|
||||
-- Stability : provisional
|
||||
-- Portability : portable
|
||||
|
||||
{-# LANGUAGE PatternGuards #-}
|
||||
{-# LANGUAGE DeriveDataTypeable #-}
|
||||
|
||||
module REPL.Monad (
|
||||
-- * REPL Monad
|
||||
REPL(..), runREPL
|
||||
, io
|
||||
, raise
|
||||
, stop
|
||||
, catch
|
||||
|
||||
-- ** Errors
|
||||
, REPLException(..)
|
||||
,rethrowEvalError
|
||||
|
||||
-- ** Environment
|
||||
, getModuleEnv, setModuleEnv
|
||||
, getTSyns, getNewtypes, getVars
|
||||
, whenDebug
|
||||
, getExprNames
|
||||
, getTypeNames
|
||||
, getPropertyNames
|
||||
, LoadedModule(..), getLoadedMod, setLoadedMod
|
||||
, builtIns
|
||||
, getPrompt
|
||||
, shouldContinue
|
||||
, unlessBatch
|
||||
, setREPLTitle
|
||||
|
||||
-- ** Config Options
|
||||
, EnvVal(..)
|
||||
, OptionDescr(..)
|
||||
, setUser, getUser, tryGetUser
|
||||
, userOptions
|
||||
|
||||
) where
|
||||
|
||||
import REPL.Trie
|
||||
|
||||
import Cryptol.Prims.Types(typeOf)
|
||||
import Cryptol.Prims.Syntax(ECon(..),ppPrefix)
|
||||
import Cryptol.Eval (EvalError)
|
||||
import qualified Cryptol.ModuleSystem as M
|
||||
import Cryptol.Parser (ParseError,ppError)
|
||||
import Cryptol.Parser.NoInclude (IncludeError,ppIncludeError)
|
||||
import Cryptol.Parser.NoPat (Error)
|
||||
import qualified Cryptol.TypeCheck.AST as T
|
||||
import Cryptol.Utils.PP
|
||||
import Cryptol.Utils.Panic (panic)
|
||||
import qualified Cryptol.Parser.AST as P
|
||||
|
||||
import Control.Monad (unless,when)
|
||||
import Data.IORef
|
||||
(IORef,newIORef,readIORef,modifyIORef)
|
||||
import Data.List (isPrefixOf)
|
||||
import Data.Typeable (Typeable)
|
||||
import System.Console.ANSI (setTitle)
|
||||
import qualified Control.Exception as X
|
||||
import qualified Data.Map as Map
|
||||
|
||||
|
||||
-- REPL Environment ------------------------------------------------------------
|
||||
|
||||
data LoadedModule = LoadedModule
|
||||
{ lName :: Maybe P.ModName -- ^ Focused module
|
||||
, lPath :: FilePath -- ^ Focused file
|
||||
}
|
||||
|
||||
-- REPL RW Environment.
|
||||
data RW = RW
|
||||
{ eLoadedMod :: Maybe LoadedModule
|
||||
, eContinue :: Bool
|
||||
, eIsBatch :: Bool
|
||||
, eModuleEnv :: M.ModuleEnv
|
||||
, eUserEnv :: UserEnv
|
||||
}
|
||||
|
||||
-- | Initial, empty environment.
|
||||
defaultRW :: Bool -> IO RW
|
||||
defaultRW isBatch = do
|
||||
env <- M.initialModuleEnv
|
||||
return RW
|
||||
{ eLoadedMod = Nothing
|
||||
, eContinue = True
|
||||
, eIsBatch = isBatch
|
||||
, eModuleEnv = env
|
||||
, eUserEnv = mkUserEnv userOptions
|
||||
}
|
||||
|
||||
-- | Build up the prompt for the REPL.
|
||||
mkPrompt :: RW -> String
|
||||
mkPrompt rw
|
||||
| eIsBatch rw = ""
|
||||
| otherwise = maybe "cryptol" pretty (lName =<< eLoadedMod rw) ++ "> "
|
||||
|
||||
mkTitle :: RW -> String
|
||||
mkTitle rw = maybe "" (\ m -> pretty m ++ " - ") (lName =<< eLoadedMod rw)
|
||||
++ "cryptol"
|
||||
|
||||
|
||||
-- REPL Monad ------------------------------------------------------------------
|
||||
|
||||
-- | REPL_ context with InputT handling.
|
||||
newtype REPL a = REPL { unREPL :: IORef RW -> IO a }
|
||||
|
||||
-- | Run a REPL action with a fresh environment.
|
||||
runREPL :: Bool -> REPL a -> IO a
|
||||
runREPL isBatch m = do
|
||||
ref <- newIORef =<< defaultRW isBatch
|
||||
unREPL m ref
|
||||
|
||||
instance Functor REPL where
|
||||
{-# INLINE fmap #-}
|
||||
fmap f m = REPL (\ ref -> fmap f (unREPL m ref))
|
||||
|
||||
instance Monad REPL where
|
||||
{-# INLINE return #-}
|
||||
return x = REPL (\_ -> return x)
|
||||
|
||||
{-# INLINE (>>=) #-}
|
||||
m >>= f = REPL $ \ref -> do
|
||||
x <- unREPL m ref
|
||||
unREPL (f x) ref
|
||||
|
||||
|
||||
-- Exceptions ------------------------------------------------------------------
|
||||
|
||||
-- | REPL exceptions.
|
||||
data REPLException
|
||||
= ParseError ParseError
|
||||
| FileNotFound FilePath
|
||||
| DirectoryNotFound FilePath
|
||||
| NoPatError [Error]
|
||||
| NoIncludeError [IncludeError]
|
||||
| EvalError EvalError
|
||||
| ModuleSystemError M.ModuleError
|
||||
| EvalPolyError T.Schema
|
||||
| TypeNotTestable T.Type
|
||||
deriving (Show,Typeable)
|
||||
|
||||
instance X.Exception REPLException
|
||||
|
||||
instance PP REPLException where
|
||||
ppPrec _ re = case re of
|
||||
ParseError e -> ppError e
|
||||
FileNotFound path -> sep [ text "File"
|
||||
, text ("`" ++ path ++ "'")
|
||||
, text"not found"
|
||||
]
|
||||
DirectoryNotFound path -> sep [ text "Directory"
|
||||
, text ("`" ++ path ++ "'")
|
||||
, text"not found or not a directory"
|
||||
]
|
||||
NoPatError es -> vcat (map pp es)
|
||||
NoIncludeError es -> vcat (map ppIncludeError es)
|
||||
ModuleSystemError me -> pp me
|
||||
EvalError e -> pp e
|
||||
EvalPolyError s -> text "Cannot evaluate polymorphic value."
|
||||
$$ text "Type:" <+> pp s
|
||||
TypeNotTestable t -> text "The expression is not of a testable type."
|
||||
$$ text "Type:" <+> pp t
|
||||
|
||||
-- | Raise an exception.
|
||||
raise :: REPLException -> REPL a
|
||||
raise exn = io (X.throwIO exn)
|
||||
|
||||
|
||||
catch :: REPL a -> (REPLException -> REPL a) -> REPL a
|
||||
catch m k = REPL (\ ref -> unREPL m ref `X.catch` \ e -> unREPL (k e) ref)
|
||||
|
||||
rethrowEvalError :: IO a -> IO a
|
||||
rethrowEvalError m = run `X.catch` rethrow
|
||||
where
|
||||
run = do
|
||||
a <- m
|
||||
return $! a
|
||||
|
||||
rethrow :: EvalError -> IO a
|
||||
rethrow exn = X.throwIO (EvalError exn)
|
||||
|
||||
|
||||
|
||||
|
||||
-- Primitives ------------------------------------------------------------------
|
||||
|
||||
io :: IO a -> REPL a
|
||||
io m = REPL (\ _ -> m)
|
||||
|
||||
getRW :: REPL RW
|
||||
getRW = REPL readIORef
|
||||
|
||||
modifyRW_ :: (RW -> RW) -> REPL ()
|
||||
modifyRW_ f = REPL (\ ref -> modifyIORef ref f)
|
||||
|
||||
-- | Construct the prompt for the current environment.
|
||||
getPrompt :: REPL String
|
||||
getPrompt = mkPrompt `fmap` getRW
|
||||
|
||||
-- | Set the name of the currently focused file, edited by @:e@ and loaded via
|
||||
-- @:r@.
|
||||
setLoadedMod :: LoadedModule -> REPL ()
|
||||
setLoadedMod n = do
|
||||
modifyRW_ (\ rw -> rw { eLoadedMod = Just n })
|
||||
setREPLTitle
|
||||
|
||||
getLoadedMod :: REPL (Maybe LoadedModule)
|
||||
getLoadedMod = eLoadedMod `fmap` getRW
|
||||
|
||||
shouldContinue :: REPL Bool
|
||||
shouldContinue = eContinue `fmap` getRW
|
||||
|
||||
stop :: REPL ()
|
||||
stop = modifyRW_ (\ rw -> rw { eContinue = False })
|
||||
|
||||
unlessBatch :: REPL () -> REPL ()
|
||||
unlessBatch body = do
|
||||
rw <- getRW
|
||||
unless (eIsBatch rw) body
|
||||
|
||||
setREPLTitle :: REPL ()
|
||||
setREPLTitle = unlessBatch $ do
|
||||
rw <- getRW
|
||||
io (setTitle (mkTitle rw))
|
||||
|
||||
builtIns :: [(String,(ECon,T.Schema))]
|
||||
builtIns = map mk [ minBound .. maxBound :: ECon ]
|
||||
where mk x = (show (ppPrefix x), (x, typeOf x))
|
||||
|
||||
-- | Only meant for use with one of getVars or getTSyns.
|
||||
keepOne :: String -> [a] -> a
|
||||
keepOne src as = case as of
|
||||
[a] -> a
|
||||
_ -> panic ("REPL: " ++ src) ["name clash in interface file"]
|
||||
|
||||
getVars :: REPL (Map.Map P.QName M.IfaceDecl)
|
||||
getVars = do
|
||||
me <- getModuleEnv
|
||||
let decls = M.focusedEnv me
|
||||
return (keepOne "getVars" `fmap` M.ifDecls decls)
|
||||
|
||||
getTSyns :: REPL (Map.Map P.QName T.TySyn)
|
||||
getTSyns = do
|
||||
me <- getModuleEnv
|
||||
let decls = M.focusedEnv me
|
||||
return (keepOne "getTSyns" `fmap` M.ifTySyns decls)
|
||||
|
||||
getNewtypes :: REPL (Map.Map P.QName T.Newtype)
|
||||
getNewtypes = do
|
||||
me <- getModuleEnv
|
||||
let decls = M.focusedEnv me
|
||||
return (keepOne "getNewtypes" `fmap` M.ifNewtypes decls)
|
||||
|
||||
-- | Get visible variable names.
|
||||
getExprNames :: REPL [String]
|
||||
getExprNames = do as <- (map getName . Map.keys) `fmap` getVars
|
||||
return (map fst builtIns ++ as)
|
||||
|
||||
-- | Get visible type signature names.
|
||||
getTypeNames :: REPL [String]
|
||||
getTypeNames =
|
||||
do tss <- getTSyns
|
||||
nts <- getNewtypes
|
||||
return $ map getName $ Map.keys tss ++ Map.keys nts
|
||||
|
||||
getPropertyNames :: REPL [String]
|
||||
getPropertyNames =
|
||||
do xs <- getVars
|
||||
return [ getName x | (x,d) <- Map.toList xs,
|
||||
T.PragmaProperty `elem` M.ifDeclPragmas d ]
|
||||
|
||||
getName :: P.QName -> String
|
||||
getName = show . pp
|
||||
|
||||
getModuleEnv :: REPL M.ModuleEnv
|
||||
getModuleEnv = eModuleEnv `fmap` getRW
|
||||
|
||||
setModuleEnv :: M.ModuleEnv -> REPL ()
|
||||
setModuleEnv me = modifyRW_ (\rw -> rw { eModuleEnv = me })
|
||||
|
||||
|
||||
-- User Environment Interaction ------------------------------------------------
|
||||
|
||||
-- | User modifiable environment, for things like numeric base.
|
||||
type UserEnv = Map.Map String EnvVal
|
||||
|
||||
data EnvVal
|
||||
= EnvString String
|
||||
| EnvNum !Int
|
||||
| EnvBool Bool
|
||||
deriving (Show)
|
||||
|
||||
-- | Generate a UserEnv from a description of the options map.
|
||||
mkUserEnv :: OptionMap -> UserEnv
|
||||
mkUserEnv opts = Map.fromList $ do
|
||||
opt <- leaves opts
|
||||
return (optName opt, optDefault opt)
|
||||
|
||||
-- | Set a user option.
|
||||
setUser :: String -> String -> REPL ()
|
||||
setUser name val = case lookupTrie name userOptions of
|
||||
|
||||
[opt] -> setUserOpt opt
|
||||
[] -> io (putStrLn ("Unknown env value `" ++ name ++ "`"))
|
||||
_ -> io (putStrLn ("Ambiguous env value `" ++ name ++ "`"))
|
||||
|
||||
where
|
||||
setUserOpt opt = case optDefault opt of
|
||||
EnvString _
|
||||
| Just err <- optCheck opt (EnvString val)
|
||||
-> io (putStrLn err)
|
||||
| otherwise
|
||||
-> writeEnv (EnvString val)
|
||||
|
||||
EnvNum _ -> case reads val of
|
||||
[(x,_)]
|
||||
| Just err <- optCheck opt (EnvNum x)
|
||||
-> io (putStrLn err)
|
||||
| otherwise
|
||||
-> writeEnv (EnvNum x)
|
||||
|
||||
_ -> io (putStrLn ("Failed to parse number for field, `" ++ name ++ "`"))
|
||||
|
||||
EnvBool _
|
||||
| any (`isPrefixOf` val) ["enable","on","yes"] ->
|
||||
writeEnv (EnvBool True)
|
||||
| any (`isPrefixOf` val) ["disable","off","no"] ->
|
||||
writeEnv (EnvBool False)
|
||||
| otherwise ->
|
||||
io (putStrLn ("Failed to parse boolean for field, `" ++ name ++ "`"))
|
||||
|
||||
writeEnv ev =
|
||||
modifyRW_ (\rw -> rw { eUserEnv = Map.insert name ev (eUserEnv rw) })
|
||||
|
||||
-- | Get a user option, using Maybe for failure.
|
||||
tryGetUser :: String -> REPL (Maybe EnvVal)
|
||||
tryGetUser name = do
|
||||
rw <- getRW
|
||||
return (Map.lookup name (eUserEnv rw))
|
||||
|
||||
-- | Get a user option, when it's known to exist. Fail with panic when it
|
||||
-- doesn't.
|
||||
getUser :: String -> REPL EnvVal
|
||||
getUser name = do
|
||||
mb <- tryGetUser name
|
||||
case mb of
|
||||
Just ev -> return ev
|
||||
Nothing -> panic "[REPL] getUser" ["option `" ++ name ++ "` does not exist"]
|
||||
|
||||
-- Environment Options ---------------------------------------------------------
|
||||
|
||||
type OptionMap = Trie OptionDescr
|
||||
|
||||
mkOptionMap :: [OptionDescr] -> OptionMap
|
||||
mkOptionMap = foldl insert emptyTrie
|
||||
where
|
||||
insert m d = insertTrie (optName d) d m
|
||||
|
||||
data OptionDescr = OptionDescr
|
||||
{ optName :: String
|
||||
, optDefault :: EnvVal
|
||||
, optCheck :: EnvVal -> Maybe String
|
||||
, optHelp :: String
|
||||
}
|
||||
|
||||
userOptions :: OptionMap
|
||||
userOptions = mkOptionMap
|
||||
[ OptionDescr "base" (EnvNum 10) checkBase
|
||||
"the base to display words at"
|
||||
, OptionDescr "debug" (EnvBool False) (const Nothing)
|
||||
"enable debugging output"
|
||||
, OptionDescr "ascii" (EnvBool False) (const Nothing)
|
||||
"display 7- or 8-bit words using ASCII notation."
|
||||
, OptionDescr "infLength" (EnvNum 5) checkInfLength
|
||||
"The number of elements to display for infinite sequences."
|
||||
, OptionDescr "tests" (EnvNum 100) (const Nothing)
|
||||
"The number of random tests to try."
|
||||
, OptionDescr "prover" (EnvString "cvc4") checkProver
|
||||
"The external smt solver for :prove and :sat (cvc4, yices, or z3)."
|
||||
, OptionDescr "iteSolver" (EnvBool False) (const Nothing)
|
||||
"Use smt solver to filter conditional branches in proofs."
|
||||
, OptionDescr "warnDefaulting" (EnvBool True) (const Nothing)
|
||||
"Choose if we should display warnings when defaulting."
|
||||
]
|
||||
|
||||
-- | Check the value to the `base` option.
|
||||
checkBase :: EnvVal -> Maybe String
|
||||
checkBase val = case val of
|
||||
EnvNum n
|
||||
| n >= 2 && n <= 36 -> Nothing
|
||||
| otherwise -> Just "base must fall between 2 and 36"
|
||||
_ -> Just "unable to parse a value for base"
|
||||
|
||||
checkInfLength :: EnvVal -> Maybe String
|
||||
checkInfLength val = case val of
|
||||
EnvNum n
|
||||
| n >= 0 -> Nothing
|
||||
| otherwise -> Just "the number of elements should be positive"
|
||||
_ -> Just "unable to parse a value for infLength"
|
||||
|
||||
checkProver :: EnvVal -> Maybe String
|
||||
checkProver val = case val of
|
||||
EnvString s
|
||||
| s `elem` ["cvc4", "yices", "z3"] -> Nothing
|
||||
| otherwise -> Just "prover must be cvc4, yices, or z3"
|
||||
_ -> Just "unable to parse a value for prover"
|
||||
|
||||
-- Environment Utilities -------------------------------------------------------
|
||||
|
||||
whenDebug :: REPL () -> REPL ()
|
||||
whenDebug m = do
|
||||
EnvBool b <- getUser "debug"
|
||||
when b m
|
46
cryptol/REPL/Trie.hs
Normal file
46
cryptol/REPL/Trie.hs
Normal file
@ -0,0 +1,46 @@
|
||||
-- |
|
||||
-- Module : $Header$
|
||||
-- Copyright : (c) 2013-2014 Galois, Inc.
|
||||
-- License : BSD3
|
||||
-- Maintainer : cryptol@galois.com
|
||||
-- Stability : provisional
|
||||
-- Portability : portable
|
||||
|
||||
module REPL.Trie where
|
||||
|
||||
import Cryptol.Utils.Panic (panic)
|
||||
import qualified Data.Map as Map
|
||||
import Data.Maybe (fromMaybe,maybeToList)
|
||||
|
||||
|
||||
-- | Maps string names to values, allowing for partial key matches and querying.
|
||||
data Trie a = Node (Map.Map Char (Trie a)) (Maybe a)
|
||||
deriving (Show)
|
||||
|
||||
emptyTrie :: Trie a
|
||||
emptyTrie = Node Map.empty Nothing
|
||||
|
||||
-- | Insert a value into the Trie. Will call `panic` if a value already exists
|
||||
-- with that key.
|
||||
insertTrie :: String -> a -> Trie a -> Trie a
|
||||
insertTrie k a = loop k
|
||||
where
|
||||
loop key (Node m mb) = case key of
|
||||
c:cs -> Node (Map.alter (Just . loop cs . fromMaybe emptyTrie) c m) mb
|
||||
[] -> case mb of
|
||||
Nothing -> Node m (Just a)
|
||||
Just _ -> panic "[REPL] Trie" ["key already exists:", "\t" ++ k]
|
||||
|
||||
-- | Return all matches with the given prefix.
|
||||
lookupTrie :: String -> Trie a -> [a]
|
||||
lookupTrie key t@(Node mp _) = case key of
|
||||
|
||||
c:cs -> case Map.lookup c mp of
|
||||
Just m' -> lookupTrie cs m'
|
||||
Nothing -> []
|
||||
|
||||
[] -> leaves t
|
||||
|
||||
-- | Return all of the values from a Trie.
|
||||
leaves :: Trie a -> [a]
|
||||
leaves (Node mp mb) = maybeToList mb ++ concatMap leaves (Map.elems mp)
|
0
docs/.gitignore
vendored
Normal file
0
docs/.gitignore
vendored
Normal file
220
docs/CryptolPrims.markdown
Normal file
220
docs/CryptolPrims.markdown
Normal file
@ -0,0 +1,220 @@
|
||||
Comparisons and Ordering
|
||||
------------------------
|
||||
|
||||
Old types:
|
||||
|
||||
(==) : {a} (fin a) => (a,a) -> Bit
|
||||
(!=) : {a} (fin a) => (a,a) -> Bit
|
||||
(===) : {a b} (fin b) => (a -> b,a -> b) -> a -> Bit
|
||||
(!===) : {a b} (fin b) => (a -> b,a -> b) -> a -> Bit
|
||||
|
||||
(<) : {n} (fin n) => ([n],[n]) -> Bit
|
||||
(>) : {n} (fin n) => ([n],[n]) -> Bit
|
||||
(<=) : {n} (fin n) => ([n],[n]) -> Bit
|
||||
(>=) : {n} (fin n) => ([n],[n]) -> Bit
|
||||
|
||||
min : {n} (fin n) => ([n],[n]) -> [n]
|
||||
max : {n} (fin n) => ([n],[n]) -> [n]
|
||||
|
||||
New types:
|
||||
|
||||
(==) : {a} (Cmp a) => a -> a -> Bit
|
||||
(!=) : {a} (Cmp a) => a -> a -> Bit
|
||||
(===) : {a,b} (Cmp b) => (a -> b) -> (a -> b) -> a -> Bit
|
||||
(!==) : {a,b} (Cmp b) => (a -> b) -> (a -> b) -> a -> Bit
|
||||
|
||||
(<) : {a} (Cmp a) => a -> a -> Bit
|
||||
(>) : {a} (Cmp a) => a -> a -> Bit
|
||||
(<=) : {a} (Cmp a) => a -> a -> Bit
|
||||
(>=) : {a} (Cmp a) => a -> a -> Bit
|
||||
|
||||
min : {a} (Cmp a) => a -> a -> a
|
||||
max : {a} (Cmp a) => a -> a -> a
|
||||
|
||||
instance Cmp Bit
|
||||
// No instance for functions.
|
||||
instance (Cmp a, fin n) => Cmp [n] a
|
||||
instance (Cmp a, Cmp b) => Cmp (a,b)
|
||||
instance (Cmp a, Cmp b) => Cmp { x : a, y : b }
|
||||
|
||||
|
||||
Arithmetic
|
||||
----------
|
||||
|
||||
Old types:
|
||||
|
||||
negate : {n a} (n >= 1) => [n]a -> [n]a
|
||||
(+) : {n a} ([n]a,[n]a) -> [n]a
|
||||
(-) : {n a} ([n]a,[n]a) -> [n]a
|
||||
(*) : {n a} ([n]a,[n]a) -> [n]a
|
||||
(/) : {n a} ([n]a,[n]a) -> [n]a
|
||||
(%) : {n a} ([n]a,[n]a) -> [n]a
|
||||
(**) : {n a} ([n]a,[n]a) -> [n]a
|
||||
|
||||
New types:
|
||||
|
||||
negate : {a} (Arith a) => a -> a
|
||||
(+) : {a} (Arith a) => a -> a -> a
|
||||
(-) : {a} (Arith a) => a -> a -> a
|
||||
(*) : {a} (Arith a) => a -> a -> a
|
||||
(/) : {a} (Arith a) => a -> a -> a
|
||||
(%) : {a} (Arith a) => a -> a -> a
|
||||
(^^) : {a} (Arith a) => a -> a -> a
|
||||
|
||||
// No instance for `Bit`.
|
||||
instance (fin n) => Arith ( [n] Bit)
|
||||
instance (Arith a) => Arith ( [n] a)
|
||||
instance (Arith b) => Arith (a -> b)
|
||||
instance (Arith a, Arith b) => Arith (a,b)
|
||||
instance (Arith a, Arith b) => Arith { x : a, y : b }
|
||||
|
||||
Note that because there is no instances for `Arith Bit`
|
||||
the top two instances do not actually overlap.
|
||||
|
||||
A corner case: unlike the old system, we'd also have to
|
||||
define `negate` at type `0`. This makes sense, there
|
||||
is only one element of type `[0]`, so it is naturally
|
||||
its own inverse, thus `negate` should behave as the
|
||||
identity function.
|
||||
|
||||
Boolean
|
||||
-------
|
||||
|
||||
Old types:
|
||||
|
||||
False : Bit
|
||||
True : Bit
|
||||
|
||||
zero : {a} a
|
||||
(&) : {a} (a,a) -> a
|
||||
(|) : {a} (a,a) -> a
|
||||
(^) : {a} (a,a) -> a
|
||||
(~) : {a} a -> a
|
||||
|
||||
New types:
|
||||
|
||||
False : Bit
|
||||
True : Bit
|
||||
|
||||
zero : (Logic a) => a
|
||||
(&&) : (Logic a) => a -> a -> a
|
||||
(||) : (Logic a) => a -> a -> a
|
||||
(^) : (Logic a) => a -> a -> a
|
||||
(~) : (Logic a) => a -> a
|
||||
|
||||
// There are instances for all types,
|
||||
// so we could potentially omit the constraints.
|
||||
instance Logic Bit
|
||||
instance Logic a => Logic ([n] a)
|
||||
instance Logic b => Logic (a -> b)
|
||||
instance (Logic a, Logic b) => Logic (a,b)
|
||||
instance (Logic a, Logic b) => Logic { x : a, y : b }
|
||||
|
||||
|
||||
Sequences
|
||||
---------
|
||||
|
||||
Old types:
|
||||
|
||||
width : {n a m} (m >= width n) => [n]a -> [m]
|
||||
|
||||
join : {n m a} [n][m]a -> [n*m]a
|
||||
split : {n m a} [n*m]a -> [n][m]a
|
||||
splitBy : {n m a} (n,[n*m]a) -> [n][m]a
|
||||
groupBy : {n m a} (m,[n*m]a) -> [n][m]a
|
||||
|
||||
(#) : {n a m} (fin n) => ([n]a,[m]a) -> [n+m]a
|
||||
tail : {n a} [n+1]a -> [n]a
|
||||
take : {n m a} (fin n,m >= n) => (n,[n+m]a) -> [n]a
|
||||
drop : {n m a} (fin n,n >= n) => (n,[n+m]a) -> [m]a
|
||||
|
||||
reverse : {n a} (fin n) => [n]a -> [n]a
|
||||
transpose : {n m a} [n][m]a -> [m][n]a
|
||||
|
||||
(@) : {n a m} ([n]a,[m]) -> a
|
||||
(@@) : {n a m i} ([n]a,[m][i]) -> [m]a
|
||||
(!) : {n a m} (fin n) => ([n]a,[m]) -> a
|
||||
(!!) : {n a m i} (fin n) => ([n]a,[m][i]) -> [m]a
|
||||
|
||||
New types:
|
||||
|
||||
length : {n,a,m} (m >= width n) => [n]a -> [m]
|
||||
|
||||
join : {parts,ench,a} (fin each) => [parts][each]a -> [parts * each]a
|
||||
split : {parts,each,a} (fin each) => [parts * each]a -> [parts][each]a
|
||||
|
||||
(#) : {front,back,a} (fin front) => [front]a -> [back]a -> [front + back]a
|
||||
splitAt : {front,back,a} (fin front) => [from + back] a -> ([front] a, [back] a)
|
||||
|
||||
reverse : {n,a} (fin n) => [n]a -> [n]a
|
||||
transpose : {n,m,a} [n][m]a -> [m][n]a
|
||||
|
||||
(@) : {n a m} [n]a -> [m] -> a
|
||||
(@@) : {n a m i} [n]a -> [m][i] -> [m]a
|
||||
(!) : {n a m} (fin n) => [n]a -> [m] -> a
|
||||
(!!) : {n a m i} (fin n) => [n]a -> [m][i] -> [m]a
|
||||
|
||||
|
||||
// Abbreviations
|
||||
splitBy n = split`{parts = n}
|
||||
groupBy n = split`{each = n}
|
||||
tail n = splitAt`{front = 1}.2
|
||||
take n = splitAt`{front = n}.1
|
||||
drop n = splitAt`{front = n}.2
|
||||
|
||||
/* Also, `length` is not really needed:
|
||||
length : {n,a,m} (m >= width n) => [n]a -> [m]
|
||||
length _ = `n
|
||||
*/
|
||||
|
||||
|
||||
Shift And Rotate
|
||||
----------------
|
||||
|
||||
Old types:
|
||||
|
||||
(<<) : {n a m} (m >= lg2 n,fin n) => ([n]a,[m]) -> [n]a
|
||||
(>>) : {n a m} (m >= lg2 n,fin n) => ([n]a,[m]) -> [n]a
|
||||
(<<<) : {n a m} (m >= lg2 n,fin n) => ([n]a,[m]) -> [n]a
|
||||
(>>>) : {n a m} (m >= lg2 n,fin n) => ([n]a,[m]) -> [n]a
|
||||
|
||||
New types:
|
||||
|
||||
(<<) : {n,a,m} (fin n, Logic a) => [n]a -> [m] -> [n]a
|
||||
(>>) : {n,a,m} (fin n, Logic a) => [n]a -> [m] -> [n]a
|
||||
(<<<) : {n,a,m} (fin n, Logic a) => [n]a -> [m] -> [n]a
|
||||
(>>>) : {n,a,m} (fin n, Logic a) => [n]a -> [m] -> [n]a
|
||||
|
||||
|
||||
Random Values
|
||||
-------------
|
||||
|
||||
Old types:
|
||||
|
||||
random : {a b} => [a] -> b
|
||||
|
||||
New types:
|
||||
|
||||
random : {a} => [32] -> a
|
||||
|
||||
|
||||
Debugging
|
||||
---------
|
||||
|
||||
ASSERT : {n a} (Bit,[n][8],a) -> a
|
||||
undefined : {a} a
|
||||
error : {n a} [n][8] -> a
|
||||
trace : {n a j} ([n][8],a,j) -> j
|
||||
|
||||
|
||||
Hints for Hardware Generation?
|
||||
------------------------------
|
||||
|
||||
pipeline_stop : {a} a -> a
|
||||
pipeline : {n a} (fin n) => ([n],a) -> a
|
||||
|
||||
seq : {n a} [n]a -> [n]a
|
||||
par : {n a} [n]a -> [n]a
|
||||
reg : {a} a -> a
|
||||
const : {a} a -> a
|
||||
|
24
docs/Makefile
Normal file
24
docs/Makefile
Normal file
@ -0,0 +1,24 @@
|
||||
MARKDOWN = Syntax.pdf CryptolPrims.pdf Version2Changes.pdf
|
||||
BOOK = Cryptol.pdf
|
||||
|
||||
.PHONY: all
|
||||
all: markdown book
|
||||
|
||||
Version2Table.pdf: Version2Table.markdown
|
||||
pandoc -f markdown+tex_math_dollars $^ -o $@
|
||||
|
||||
.PHONY: markdown
|
||||
markdown: ${MARKDOWN}
|
||||
|
||||
.PHONY: book
|
||||
book:
|
||||
(cd ProgrammingCryptol; make)
|
||||
cp ProgrammingCryptol/tmp/${BOOK} .
|
||||
|
||||
%.pdf: %.markdown
|
||||
pandoc $^ --toc -o $@
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f ${MARKDOWN}
|
||||
rm -f ${BOOK}
|
14
docs/ProgrammingCryptol/.gitignore
vendored
Normal file
14
docs/ProgrammingCryptol/.gitignore
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
*.SPELLNEW
|
||||
*.SPELLOLD
|
||||
*.aux
|
||||
*.bbl
|
||||
*.blg
|
||||
*.brf
|
||||
*.idx
|
||||
*.ilg
|
||||
*.ind
|
||||
*.log
|
||||
*.out
|
||||
*.toc
|
||||
.*.swp
|
||||
/tmp
|
84
docs/ProgrammingCryptol/Makefile
Normal file
84
docs/ProgrammingCryptol/Makefile
Normal file
@ -0,0 +1,84 @@
|
||||
TARGET = Cryptol
|
||||
TMP = tmp
|
||||
MAIN = main
|
||||
MAINTARGET= ${MAIN}/${TARGET}
|
||||
TMPTARGET = ${TMP}/${TARGET}
|
||||
SRCS = ${wildcard *.tex */*.tex *.sty */*.sty} ${wildcard *.bib */*.bib} \
|
||||
${wildcard *.sty} Makefile ${wildcard *.cry */*.cry}
|
||||
SPELLSRC = ${filter-out ${wildcard utils/*.tex}, ${wildcard *.tex */*.tex}}
|
||||
LTMPDIR = tmp
|
||||
NEWSPELL = ${LTMPDIR}/${TARGET}.SPELLNEW
|
||||
OLDSPELL = ${LTMPDIR}/${TARGET}.SPELLOLD
|
||||
SPELL = aspell -t -l
|
||||
AUX = ${wildcard ${TMP}/*.blg} ${wildcard ${TMP}/*.bbl} ${wildcard ${TMP}/*.aux} \
|
||||
${wildcard ${TMP}/*.eps} ${wildcard ${TMP}/*.log} ${wildcard ${TMP}/*.toc} \
|
||||
${wildcard ${TMP}/*.out} ${wildcard ${TMP}/*.idx} ${wildcard ${TMP}/*.ilg} \
|
||||
${wildcard ${TMP}/*.ind} ${wildcard ${TMP}/*.brf} ${wildcard ${TMP}/*.glg} \
|
||||
${wildcard ${TMP}/*.glo} ${wildcard ${TMP}/*.gls} ${wildcard ${TMP}/*.ist} \
|
||||
|
||||
LATEX = xelatex -output-driver=xdvipdfmx -output-directory=${TMP} -halt-on-error -file-line-error
|
||||
BIBTEX = bibtex
|
||||
MAKEINDEX = makeindex
|
||||
|
||||
# TODO: Switch to using pdflatex or rubber?
|
||||
# TODO: Ensure that TEXINPUTS is set correctly to make \includes and \usepackages more robust?
|
||||
|
||||
all: pdf
|
||||
cp ${TMP}/Cryptol.pdf ..
|
||||
|
||||
test:
|
||||
cd aes ; make test
|
||||
cd highAssurance ; make test
|
||||
cd enigma ; make test
|
||||
|
||||
pdf: ${TARGET}.pdf
|
||||
|
||||
${TMP}:
|
||||
mkdir -p ${TMP}
|
||||
|
||||
${TARGET}.pdf: ${SRCS} ${TMP}
|
||||
# surely I don't need this many latex's and indexes etc; but this looks like a sure fire way of
|
||||
# getting numbers right.. heh
|
||||
${LATEX} ${MAINTARGET}
|
||||
${MAKEINDEX} ${TMP}/Cryptol.glo -s ${TMP}/Cryptol.ist -t ${TMP}/Cryptol.glg -o ${TMP}/Cryptol.gls
|
||||
${MAKEINDEX} ${TMPTARGET}
|
||||
${BIBTEX} ${TMPTARGET}
|
||||
${LATEX} ${MAINTARGET}
|
||||
${MAKEINDEX} ${TMPTARGET}
|
||||
${MAKEINDEX} ${TMP}/Cryptol.glo -s ${TMP}/Cryptol.ist -t ${TMP}/Cryptol.glg -o ${TMP}/Cryptol.gls
|
||||
${BIBTEX} ${TMPTARGET}
|
||||
${LATEX} ${MAINTARGET}
|
||||
${LATEX} ${MAINTARGET}
|
||||
|
||||
# for quickly seeing changes; might get the labels wrong
|
||||
quick: ${SRCS}
|
||||
${LATEX} ${MAINTARGET}
|
||||
|
||||
# load into Cryptol
|
||||
cry:
|
||||
cryptol-2 ${MAINTARGET}.tex
|
||||
# TODO see ticket #276
|
||||
# cryptol -n ${MAINTARGET}
|
||||
|
||||
.PHONY: spellClean superClean clean quickSpell
|
||||
|
||||
clean:
|
||||
rm -f ${AUX}
|
||||
|
||||
superClean: clean
|
||||
rm -f ${TARGET}.pdf
|
||||
make -C tools clean
|
||||
|
||||
spellClean:
|
||||
rm -f ${NEWSPELL} ${OLDSPELL}
|
||||
|
||||
quickSpell:
|
||||
@touch ${NEWSPELL}
|
||||
@mv -f ${NEWSPELL} ${OLDSPELL}
|
||||
@cat ${SPELLSRC} | ${SPELL} | tr "A-Z" "a-z" | sort | uniq | less > ${NEWSPELL}
|
||||
@echo '(The ones marked with < are new.)'
|
||||
@diff ${NEWSPELL} ${OLDSPELL}
|
||||
|
||||
.PHONY: continuous
|
||||
continuous:
|
||||
@make -C tools
|
1
docs/ProgrammingCryptol/aes/.gitignore
vendored
Normal file
1
docs/ProgrammingCryptol/aes/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/auto
|
239
docs/ProgrammingCryptol/aes/AES.cry
Normal file
239
docs/ProgrammingCryptol/aes/AES.cry
Normal file
@ -0,0 +1,239 @@
|
||||
// Cryptol AES Implementation
|
||||
// Copyright (c) 2010-2013, Galois Inc.
|
||||
// www.cryptol.net
|
||||
// You can freely use this source code for educational purposes.
|
||||
|
||||
// This is a fairly close implementation of the FIPS-197 standard:
|
||||
// http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
|
||||
// Nk: Number of blocks in the key
|
||||
// Must be one of 4 (AES128), 6 (AES192), or 8 (AES256)
|
||||
// Aside from this line, no other code below needs to change for
|
||||
// implementing AES128, AES192, or AES256
|
||||
module AES where
|
||||
|
||||
type AES128 = 4
|
||||
type AES192 = 6
|
||||
type AES256 = 8
|
||||
|
||||
type Nk = AES128
|
||||
|
||||
// For Cryptol 2.x | x > 0
|
||||
// NkValid: `Nk -> Bit
|
||||
// property NkValid k = (k == `AES128) || (k == `AES192) || (k == `AES256)
|
||||
|
||||
// Number of blocks and Number of rounds
|
||||
type Nb = 4
|
||||
type Nr = 6 + Nk
|
||||
|
||||
type AESKeySize = (Nk*32)
|
||||
|
||||
// Helper type definitions
|
||||
type GF28 = [8]
|
||||
type State = [4][Nb]GF28
|
||||
type RoundKey = State
|
||||
type KeySchedule = (RoundKey, [Nr-1]RoundKey, RoundKey)
|
||||
// GF28 operations
|
||||
gf28Add : {n} (fin n) => [n]GF28 -> GF28
|
||||
gf28Add ps = sums ! 0
|
||||
where sums = [zero] # [ p ^ s | p <- ps | s <- sums ]
|
||||
|
||||
irreducible = <| x^^8 + x^^4 + x^^3 + x + 1 |>
|
||||
|
||||
gf28Mult : (GF28, GF28) -> GF28
|
||||
gf28Mult (x, y) = pmod(pmult x y) irreducible
|
||||
|
||||
gf28Pow : (GF28, [8]) -> GF28
|
||||
gf28Pow (n, k) = pow k
|
||||
where sq x = gf28Mult (x, x)
|
||||
odd x = x ! 0
|
||||
pow i = if i == 0 then 1
|
||||
else if odd i
|
||||
then gf28Mult(n, sq (pow (i >> 1)))
|
||||
else sq (pow (i >> 1))
|
||||
|
||||
gf28Inverse : GF28 -> GF28
|
||||
gf28Inverse x = gf28Pow (x, 254)
|
||||
|
||||
gf28DotProduct : {n} (fin n) => ([n]GF28, [n]GF28) -> GF28
|
||||
gf28DotProduct (xs, ys) = gf28Add [ gf28Mult (x, y) | x <- xs
|
||||
| y <- ys ]
|
||||
|
||||
gf28VectorMult : {n, m} (fin n) => ([n]GF28, [m][n]GF28) -> [m]GF28
|
||||
gf28VectorMult (v, ms) = [ gf28DotProduct(v, m) | m <- ms ]
|
||||
|
||||
gf28MatrixMult : {n, m, k} (fin m) => ([n][m]GF28, [m][k]GF28) -> [n][k]GF28
|
||||
gf28MatrixMult (xss, yss) = [ gf28VectorMult(xs, yss') | xs <- xss ]
|
||||
where yss' = transpose yss
|
||||
|
||||
// The affine transform and its inverse
|
||||
xformByte : GF28 -> GF28
|
||||
xformByte b = gf28Add [b, (b >>> 4), (b >>> 5), (b >>> 6), (b >>> 7), c]
|
||||
where c = 0x63
|
||||
|
||||
xformByte' : GF28 -> GF28
|
||||
xformByte' b = gf28Add [(b >>> 2), (b >>> 5), (b >>> 7), d] where d = 0x05
|
||||
// The SubBytes transform and its inverse
|
||||
SubByte : GF28 -> GF28
|
||||
SubByte b = xformByte (gf28Inverse b)
|
||||
|
||||
SubByte' : GF28 -> GF28
|
||||
SubByte' b = sbox@b
|
||||
|
||||
SubBytes : State -> State
|
||||
SubBytes state = [ [ SubByte' b | b <- row ] | row <- state ]
|
||||
|
||||
|
||||
InvSubByte : GF28 -> GF28
|
||||
InvSubByte b = gf28Inverse (xformByte' b)
|
||||
|
||||
InvSubBytes : State -> State
|
||||
InvSubBytes state =[ [ InvSubByte b | b <- row ] | row <- state ]
|
||||
|
||||
// The ShiftRows transform and its inverse
|
||||
ShiftRows : State -> State
|
||||
ShiftRows state = [ row <<< shiftAmount | row <- state
|
||||
| shiftAmount <- [0 .. 3]
|
||||
]
|
||||
|
||||
InvShiftRows : State -> State
|
||||
InvShiftRows state = [ row >>> shiftAmount | row <- state
|
||||
| shiftAmount <- [0 .. 3]
|
||||
]
|
||||
|
||||
// The MixColumns transform and its inverse
|
||||
MixColumns : State -> State
|
||||
MixColumns state = gf28MatrixMult (m, state)
|
||||
where m = [[2, 3, 1, 1],
|
||||
[1, 2, 3, 1],
|
||||
[1, 1, 2, 3],
|
||||
[3, 1, 1, 2]]
|
||||
|
||||
InvMixColumns : State -> State
|
||||
InvMixColumns state = gf28MatrixMult (m, state)
|
||||
where m = [[0x0e, 0x0b, 0x0d, 0x09],
|
||||
[0x09, 0x0e, 0x0b, 0x0d],
|
||||
[0x0d, 0x09, 0x0e, 0x0b],
|
||||
[0x0b, 0x0d, 0x09, 0x0e]]
|
||||
|
||||
// The AddRoundKey transform
|
||||
AddRoundKey : (RoundKey, State) -> State
|
||||
AddRoundKey (rk, s) = rk ^ s
|
||||
// Key expansion
|
||||
Rcon : [8] -> [4]GF28
|
||||
Rcon i = [(gf28Pow (<| x |>, i-1)), 0, 0, 0]
|
||||
|
||||
SubWord : [4]GF28 -> [4]GF28
|
||||
SubWord bs = [ SubByte b | b <- bs ]
|
||||
|
||||
RotWord : [4]GF28 -> [4]GF28
|
||||
RotWord [a0, a1, a2, a3] = [a1, a2, a3, a0]
|
||||
|
||||
NextWord : ([8],[4][8],[4][8]) -> [4][8]
|
||||
NextWord(i, prev, old) = old ^ mask
|
||||
where mask = if i % `Nk == 0
|
||||
then SubWord(RotWord(prev)) ^ Rcon (i / `Nk)
|
||||
else if (`Nk > 6) && (i % `Nk == 4)
|
||||
then SubWord(prev)
|
||||
else prev
|
||||
|
||||
|
||||
ExpandKeyForever : [Nk][4][8] -> [inf]RoundKey
|
||||
ExpandKeyForever seed = [ transpose g | g <- groupBy`{4} (keyWS seed) ]
|
||||
|
||||
keyWS : [Nk][4][8] -> [inf][4][8]
|
||||
keyWS seed = xs
|
||||
where xs = seed # [ NextWord(i, prev, old)
|
||||
| i <- [ `Nk ... ]
|
||||
| prev <- drop`{Nk-1} xs
|
||||
| old <- xs
|
||||
]
|
||||
|
||||
checkKey = take`{16} (drop`{8} (keyWS ["abcd", "defg", "1234", "5678"]))
|
||||
checkKey2 = [transpose g | g <- groupBy`{4}checkKey]
|
||||
|
||||
ExpandKey : [AESKeySize] -> KeySchedule
|
||||
ExpandKey key = (keys @ 0, keys @@ [1 .. (Nr - 1)], keys @ `Nr)
|
||||
where seed : [Nk][4][8]
|
||||
seed = split (split key)
|
||||
keys = ExpandKeyForever seed
|
||||
|
||||
fromKS : KeySchedule -> [Nr+1][4][32]
|
||||
fromKS (f, ms, l) = [ formKeyWords (transpose k) | k <- [f] # ms # [l] ]
|
||||
where formKeyWords bbs = [ join bs | bs <- bbs ]
|
||||
|
||||
// AES rounds and inverses
|
||||
AESRound : (RoundKey, State) -> State
|
||||
AESRound (rk, s) = AddRoundKey (rk, MixColumns (ShiftRows (SubBytes s)))
|
||||
|
||||
AESFinalRound : (RoundKey, State) -> State
|
||||
AESFinalRound (rk, s) = AddRoundKey (rk, ShiftRows (SubBytes s))
|
||||
|
||||
AESInvRound : (RoundKey, State) -> State
|
||||
AESInvRound (rk, s) =
|
||||
InvMixColumns (AddRoundKey (rk, InvSubBytes (InvShiftRows s)))
|
||||
AESFinalInvRound : (RoundKey, State) -> State
|
||||
AESFinalInvRound (rk, s) = AddRoundKey (rk, InvSubBytes (InvShiftRows s))
|
||||
|
||||
// Converting a 128 bit message to a State and back
|
||||
msgToState : [128] -> State
|
||||
msgToState msg = transpose (split (split msg))
|
||||
|
||||
stateToMsg : State -> [128]
|
||||
stateToMsg st = join (join (transpose st))
|
||||
|
||||
// AES Encryption
|
||||
aesEncrypt : ([128], [AESKeySize]) -> [128]
|
||||
aesEncrypt (pt, key) = stateToMsg (AESFinalRound (kFinal, rounds ! 0))
|
||||
where (kInit, ks, kFinal) = ExpandKey key
|
||||
state0 = AddRoundKey(kInit, msgToState pt)
|
||||
rounds = [state0] # [ AESRound (rk, s) | rk <- ks
|
||||
| s <- rounds
|
||||
]
|
||||
|
||||
// AES Decryption
|
||||
aesDecrypt : ([128], [AESKeySize]) -> [128]
|
||||
aesDecrypt (ct, key) = stateToMsg (AESFinalInvRound (kFinal, rounds ! 0))
|
||||
where (kFinal, ks, kInit) = ExpandKey key
|
||||
state0 = AddRoundKey(kInit, msgToState ct)
|
||||
rounds = [state0] # [ AESInvRound (rk, s)
|
||||
| rk <- reverse ks
|
||||
| s <- rounds
|
||||
]
|
||||
|
||||
sbox : [256]GF28
|
||||
sbox = [
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67,
|
||||
0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59,
|
||||
0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7,
|
||||
0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1,
|
||||
0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05,
|
||||
0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83,
|
||||
0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29,
|
||||
0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
|
||||
0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa,
|
||||
0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c,
|
||||
0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc,
|
||||
0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
|
||||
0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19,
|
||||
0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee,
|
||||
0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49,
|
||||
0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
|
||||
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4,
|
||||
0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6,
|
||||
0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70,
|
||||
0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9,
|
||||
0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e,
|
||||
0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1,
|
||||
0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0,
|
||||
0x54, 0xbb, 0x16]
|
||||
|
||||
// Test runs:
|
||||
|
||||
// cryptol> aesEncrypt (0x3243f6a8885a308d313198a2e0370734, \
|
||||
// 0x2b7e151628aed2a6abf7158809cf4f3c)
|
||||
// 0x3925841d02dc09fbdc118597196a0b32
|
||||
// cryptol> aesEncrypt (0x00112233445566778899aabbccddeeff, \
|
||||
// 0x000102030405060708090a0b0c0d0e0f)
|
||||
// 0x69c4e0d86a7b0430d8cdb78070b4c55a
|
||||
property AESCorrect msg key = aesDecrypt (aesEncrypt (msg, key), key) == msg
|
1522
docs/ProgrammingCryptol/aes/AES.tex
Normal file
1522
docs/ProgrammingCryptol/aes/AES.tex
Normal file
File diff suppressed because it is too large
Load Diff
28
docs/ProgrammingCryptol/aes/AESCode.tex
Normal file
28
docs/ProgrammingCryptol/aes/AESCode.tex
Normal file
@ -0,0 +1,28 @@
|
||||
\chapter{AES in Cryptol}\label{app:aes}
|
||||
|
||||
In this appendix we present the Cryptol code for the AES\indAES in its
|
||||
entirety for reference purposes. Chapter~\ref{chapter:aes} has a
|
||||
detailed discussion on how AES works, and the construction of the
|
||||
Cryptol model below.
|
||||
|
||||
In the below code, simply set {\tt Nk} to be 4 for AES128, 6 for
|
||||
AES192, and 8 for AES256 on line 15. No other modifications are
|
||||
required for obtaining these AES variants. Note that we have
|
||||
rearranged the code given in Chapter~\ref{chapter:aes} below for ease
|
||||
of reading.
|
||||
%% and eliminated the theorem declarations for simplicity.
|
||||
|
||||
\fvset{fontsize=\footnotesize}
|
||||
\VerbatimInput[numbers=left]{aes/AES.cry}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
AESEncapsulated = {
|
||||
include "AES.cry";
|
||||
};
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
5
docs/ProgrammingCryptol/aes/Makefile
Normal file
5
docs/ProgrammingCryptol/aes/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
Enigma.cry:
|
||||
ln -s ../enigma/Enigma.cry .
|
||||
|
||||
test: Enigma.cry
|
||||
cryptol-2 -b sanity.icry
|
3
docs/ProgrammingCryptol/aes/sanity.icry
Normal file
3
docs/ProgrammingCryptol/aes/sanity.icry
Normal file
@ -0,0 +1,3 @@
|
||||
:set warnDefaulting=off
|
||||
:l AES.tex
|
||||
sanityCheck
|
17
docs/ProgrammingCryptol/appendices/grammar.tex
Normal file
17
docs/ProgrammingCryptol/appendices/grammar.tex
Normal file
@ -0,0 +1,17 @@
|
||||
\chapter{The Cryptol Syntax and Grammar}
|
||||
\label{cha:crypt-synt-gramm}
|
||||
|
||||
\todo[inline]{To be written or, preferably, generated.}
|
||||
|
||||
%=====================================================================
|
||||
\section{A Cryptol syntax summary}
|
||||
\label{sec:crypt-synt-summ}
|
||||
|
||||
%=====================================================================
|
||||
\section{The Cryptol Grammar}
|
||||
\label{sec:cryptol-grammar}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
46
docs/ProgrammingCryptol/basic/Basic.tex
Normal file
46
docs/ProgrammingCryptol/basic/Basic.tex
Normal file
@ -0,0 +1,46 @@
|
||||
\chapter{Basic Examples}
|
||||
\label{cha:basic-examples}
|
||||
|
||||
To be written.
|
||||
|
||||
\todo[inline]{Hello, world Cryptol equivalent.}
|
||||
|
||||
\todo[inline]{Counting.}
|
||||
|
||||
\todo[inline]{Fib.}
|
||||
|
||||
\todo[inline]{dumb sorting, bitonic sort}
|
||||
|
||||
\todo[inline]{Carefully discuss function application semantics and how
|
||||
they differ from what mathematicians are used to. Relevant to
|
||||
\href{https://www.galois.com/cryptol/ticket/280}{ticket \#280}.}
|
||||
|
||||
\todo[inline]{Existing blogs: Legato, NQueens, Sudoku, substitution
|
||||
ciphers, riffle shuffle}
|
||||
|
||||
\todo[inline]{Existing crypto in blogs/text: MD6, BASE64, SIMON and SPECK,
|
||||
ZUC, Skein, the rail fence cipher}
|
||||
|
||||
\todo[inline]{Crypto we need to do: MD1, MD2, MD3, MD4, MD5}
|
||||
|
||||
\todo[inline]{Other fun stuff: (that hasn't been written about):
|
||||
U2Bridge crossing, foxGooseBeans, prolog}
|
||||
|
||||
\todo[inline]{Hamming encryption?}
|
||||
|
||||
\todo[inline]{fixed table lookup compression, run-length encoding,
|
||||
Huffman encoding}
|
||||
|
||||
\todo[inline]{searching on finite datatypes and infinite streams}
|
||||
|
||||
\todo[inline]{integer FFT}
|
||||
|
||||
\todo[inline]{put in something about cordic/floating
|
||||
point\indFloatingPoint}
|
||||
|
||||
\todo[inline]{Fix all uses of Example references using \texttt{autoref}.}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
248
docs/ProgrammingCryptol/bib/cryptol.bib
Normal file
248
docs/ProgrammingCryptol/bib/cryptol.bib
Normal file
@ -0,0 +1,248 @@
|
||||
@Unpublished{CryptolWWW,
|
||||
key = "Cryptol",
|
||||
note = {\url{http://www.cryptol.net}},
|
||||
title = {{Cryptol} web site},
|
||||
}
|
||||
|
||||
@Unpublished{enigmaAnomaly,
|
||||
author = "Andy Carlson",
|
||||
note = {\url{http://homepages.tesco.net/~andycarlson/enigma/simulating_enigma.html}, see the section ``Wheel Turnover and The Anomaly''},
|
||||
title = {Simulating the Enigma Cypher Machine},
|
||||
}
|
||||
|
||||
@Unpublished{ABCTool,
|
||||
author = {Alan Mishchenko},
|
||||
note = {Release 70930, Available at: \url{http://www.eecs.berkeley.edu/~alanmi/abc}},
|
||||
title = {{ABC}: System for Sequential Synthesis and Verification},
|
||||
year = 2007,
|
||||
}
|
||||
|
||||
@Unpublished{YicesWWW,
|
||||
key = "Yices",
|
||||
note = {\url{http://yices.csl.sri.com/}},
|
||||
title = {{Yices} web site},
|
||||
}
|
||||
|
||||
@Unpublished{cvc4WWW,
|
||||
key = "The CVC4 SMT Solver",
|
||||
note = {\url{http://cvc4.cs.nyu.edu/web/}},
|
||||
title = {{CVC4} web site}
|
||||
}
|
||||
|
||||
@Unpublished{Z3WWW,
|
||||
key = "The Z3 theorem prover",
|
||||
note = {\url{http://z3.codeplex.com/}},
|
||||
title = {{Z3} web site}
|
||||
}
|
||||
|
||||
@Book{Isabelle-book,
|
||||
author = {T.~Nipkow and L.~C.~Paulson and M.~Wenzel},
|
||||
title = {{Isabelle/HOL} -- A Proof Assistant for Higher-Order Logic},
|
||||
series = {LNCS 2283},
|
||||
publisher = {Springer},
|
||||
year = 2002
|
||||
}
|
||||
|
||||
@Inproceedings{erkok-matthews-cryptolEqChecking-09,
|
||||
author = "Levent {Erk\"{o}k} and John Matthews",
|
||||
title = "Pragmatic Equivalence and Safety Checking in {C}ryptol",
|
||||
booktitle = "Programming Languages meets Program Verification, PLPV'09,
|
||||
Savannah, Georgia, USA",
|
||||
publisher = "ACM Press",
|
||||
month = jan,
|
||||
pages = "73--81",
|
||||
year = "2009",
|
||||
}
|
||||
|
||||
@Inproceedings{erkok-carlsson-wick-cryptolCoverification-09,
|
||||
author = "Levent {Erk\"{o}k} and Magnus Carlsson and Adam Wick",
|
||||
title = "Hardware/Software Co-verification of Cryptographic Algorithms using {C}ryptol",
|
||||
booktitle = "Formal Methods in Computer Aided Design, FMCAD'09,
|
||||
Austin, TX, USA",
|
||||
publisher = "IEEE",
|
||||
month = nov,
|
||||
pages = "188--191",
|
||||
year = "2009",
|
||||
}
|
||||
|
||||
@book{Hin97,
|
||||
author = "J. Roger Hindley",
|
||||
title = "Basic Simple Type Theory",
|
||||
volume = "42",
|
||||
publisher = "Cambridge University Press",
|
||||
address = "Cambridge, UK",
|
||||
year = "1997",
|
||||
}
|
||||
|
||||
@Unpublished{Has98,
|
||||
author = {Simon L. {Peyton Jones} and John Hughes},
|
||||
title = {{(Editors.) Report} on the programming language
|
||||
{Haskell} 98, a non-strict purely-functional programming
|
||||
language},
|
||||
year = {1999},
|
||||
month = feb,
|
||||
note = {URL: \url{www.haskell.org/onlinereport}},
|
||||
}
|
||||
|
||||
@book{ML,
|
||||
author = {Milner, Robin and Tofte, Mads and Macqueen, David},
|
||||
title = {The Definition of Standard ML},
|
||||
year = {1997},
|
||||
isbn = {0262631814},
|
||||
publisher = {MIT Press},
|
||||
address = {Cambridge, MA, USA},
|
||||
}
|
||||
|
||||
@INPROCEEDINGS{lewis2003,
|
||||
author = {Lewis, J. R. and Martin, B.},
|
||||
title = {Cryptol: high assurance, retargetable crypto development and validation},
|
||||
pages = {820--825},
|
||||
volume = 2,
|
||||
crossref = {milcom2003},
|
||||
abstract = {As cryptography becomes more vital to the infrastructure of
|
||||
computing systems, it becomes increasingly vital to be able to
|
||||
rapidly and correctly produce new implementations of
|
||||
cryptographic algorithms. To address these challenges, we
|
||||
introduce a new, formal methods-based approach to the
|
||||
specification and implementation of cryptography, present a
|
||||
number of scenarios of use, an overview of the language, and
|
||||
present part of a specification of the advanced encryption
|
||||
standard.},
|
||||
}
|
||||
|
||||
@PROCEEDINGS{milcom2003,
|
||||
title = {Military Communications Conference 2003},
|
||||
booktitle = {Military Communications Conference 2003},
|
||||
month = OCT,
|
||||
year = 2003,
|
||||
publisher = {IEEE},
|
||||
}
|
||||
|
||||
@misc{aes,
|
||||
Author = {{National Institute of Standards and Technology, NIST}},
|
||||
Month = {November},
|
||||
Note = {{FIPS} Publication 197},
|
||||
Title = {Announcing the {AES}},
|
||||
howpublished = {\url{http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf}},
|
||||
Year = {2001},
|
||||
}
|
||||
|
||||
@Book{Bir98,
|
||||
author = "Richard Bird",
|
||||
title = "Introduction to Functional Programming using Haskell",
|
||||
edition = "second",
|
||||
publisher = "Printice Hall Europe",
|
||||
address = "London",
|
||||
year = "1998",
|
||||
}
|
||||
|
||||
@misc{wiki:fibonacci,
|
||||
author = "Wikipedia",
|
||||
title = "Fibonacci number --- Wikipedia{,} The Free Encyclopedia",
|
||||
year = "2010",
|
||||
howpublished = "\url{http://en.wikipedia.org/w/index.php?title=Fibonacci_number&oldid=390711214}",
|
||||
note = "[Online; accessed 15-October-2010]"
|
||||
}
|
||||
|
||||
@Book{Singh:1999:CBE,
|
||||
author = "Simon Singh",
|
||||
title = "The code book: the evolution of secrecy from {Mary,
|
||||
Queen of Scots}, to quantum cryptography",
|
||||
publisher = "Doubleday",
|
||||
address = "New York, NY, USA",
|
||||
pages = "xiii + 402",
|
||||
year = "1999",
|
||||
ISBN = "0-385-49531-5",
|
||||
}
|
||||
|
||||
@Book{TheCProgrammingLanguage,
|
||||
author = "Kernighan, Brian W. and Richie, Dennis M.",
|
||||
title = "{The C Programming Language}",
|
||||
publisher = "Prentice Hall",
|
||||
year = "1998",
|
||||
edition = "Second",
|
||||
}
|
||||
|
||||
|
||||
@misc{wiki:scytale,
|
||||
author = "Wikipedia",
|
||||
title = "Scytale --- Wikipedia{,} The Free Encyclopedia",
|
||||
year = "2010",
|
||||
howpublished = "\url{http://en.wikipedia.org/w/index.php?title=Scytale&oldid=391405769}",
|
||||
note = "[Online; accessed 19-October-2010]"
|
||||
}
|
||||
|
||||
@misc{wiki:vigenere,
|
||||
author = "Wikipedia",
|
||||
title = "Vigenere cipher --- Wikipedia{,} The Free Encyclopedia",
|
||||
year = "2010",
|
||||
howpublished = "\url{http://en.wikipedia.org/w/index.php?title=Vigenere_cipher&oldid=389811286}",
|
||||
note = "[Online; accessed 19-October-2010]"
|
||||
}
|
||||
|
||||
@misc{wiki:substitution,
|
||||
author = "Wikipedia",
|
||||
title = "Substitution cipher --- Wikipedia{,} The Free Encyclopedia",
|
||||
year = "2010",
|
||||
howpublished = "\url{http://en.wikipedia.org/w/index.php?title=Substitution_cipher&oldid=389116332}",
|
||||
note = "[Online; accessed 20-October-2010]"
|
||||
}
|
||||
|
||||
@misc{wiki:enigma,
|
||||
author = "Wikipedia",
|
||||
title = "Enigma machine --- Wikipedia{,} The Free Encyclopedia",
|
||||
year = "2010",
|
||||
howpublished = "\url{http://en.wikipedia.org/w/index.php?title=Enigma_machine&oldid=392040616}",
|
||||
note = "[Online; accessed 21-October-2010]"
|
||||
}
|
||||
|
||||
@misc{wiki:enigmarotors,
|
||||
author = "Wikipedia",
|
||||
title = "Enigma rotor details --- Wikipedia{,} The Free Encyclopedia",
|
||||
year = "2010",
|
||||
howpublished = "\url{http://en.wikipedia.org/w/index.php?title=Enigma_rotor_details&oldid=389862975}",
|
||||
note = "[Online; accessed 25-October-2010]"
|
||||
}
|
||||
|
||||
@inproceedings{quickcheck
|
||||
, title = { {QuickCheck}: A Lightweight Tool for Random Testing
|
||||
of {Haskell} Programs }
|
||||
, author = { Koen Claessen
|
||||
and John Hughes }
|
||||
, booktitle = { Proc.\ of International Conference on Functional Programming
|
||||
(ICFP) }
|
||||
, publisher = { ACM SIGPLAN }
|
||||
, year = { 2000 }
|
||||
}
|
||||
|
||||
@book{DaemenR02,
|
||||
author = {Joan Daemen and
|
||||
Vincent Rijmen},
|
||||
title = {The Design of Rijndael: {AES} - {T}he {A}dvanced {E}ncryption {S}tandard},
|
||||
publisher = {Springer},
|
||||
year = {2002},
|
||||
isbn = {3-540-42580-2},
|
||||
}
|
||||
|
||||
@misc{wiki:galoisfield,
|
||||
author = "Wikipedia",
|
||||
title = "Finite field arithmetic --- Wikipedia{,} The Free Encyclopedia",
|
||||
year = "2010",
|
||||
url = "\url{http://en.wikipedia.org/w/index.php?title=Finite_field_arithmetic&oldid=350976765}",
|
||||
note = "[Online; accessed 10-November-2010]"
|
||||
}
|
||||
|
||||
@misc{wiki:polydiv,
|
||||
author = "Wikipedia",
|
||||
title = "Polynomial long division --- Wikipedia{,} The Free Encyclopedia",
|
||||
year = "2010",
|
||||
url = "\url{http://en.wikipedia.org/w/index.php?title=Polynomial_long_division&oldid=393501903}",
|
||||
note = "[Online; accessed 10-November-2010]"
|
||||
}
|
||||
|
||||
@book{DecisionProcedures2008,
|
||||
author = {Daniel Kroening and Ofer Strichman},
|
||||
title = {Decision Procedures: An Algorithmic Point of View},
|
||||
year = {2008},
|
||||
publisher = {Springer},
|
||||
}
|
1
docs/ProgrammingCryptol/classic/.gitignore
vendored
Normal file
1
docs/ProgrammingCryptol/classic/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/auto
|
782
docs/ProgrammingCryptol/classic/Classic.tex
Normal file
782
docs/ProgrammingCryptol/classic/Classic.tex
Normal file
@ -0,0 +1,782 @@
|
||||
\chapter{Classic ciphers}
|
||||
\label{chapter:classic}
|
||||
|
||||
Modern cryptography has come a long way. In his excellent book on
|
||||
cryptography, Singh traces it back to at least 5th century B.C., to
|
||||
the times of Herodotus and the ancient Greeks~\cite{Singh:1999:CBE}.
|
||||
That's some 2500 years ago, and surely we do not use those methods
|
||||
anymore in modern day cryptography. However, the basic techniques are
|
||||
still relevant for appreciating the art of secret writing.
|
||||
|
||||
Shift ciphers\indShiftcipher construct the \glosCiphertext
|
||||
ciphertext\indCiphertext from the \glosPlaintext
|
||||
plaintext\indPlaintext\ by means of a predefined {\em shifting}
|
||||
operation,\glosCipherkey where the cipherkey of a particular shift
|
||||
algorithm defines the shift amount of the cipher.\indCipherkey
|
||||
Transposition ciphers work by keeping the plaintext the same, but {\em
|
||||
rearrange} the order of the characters according to a certain rule.
|
||||
The cipherkey is essentially the description of how this transposition
|
||||
is done.\indTranspositioncipher Substitution
|
||||
ciphers\indSubstitutioncipher generalize shifts and transpositions,
|
||||
allowing one to substitute arbitrary codes for plaintext elements. In
|
||||
this chapter, we will study several examples of these techniques and
|
||||
see how we can code them in Cryptol.
|
||||
|
||||
In general, ciphers boil down to pairs of functions \emph{encrypt} and
|
||||
\emph{decrypt} which ``fit together'' in the appropriate way. Arguing
|
||||
that a cryptographic function is \emph{correct} is subtle.
|
||||
|
||||
Correctness of cryptography is determined by cryptanalyses by expert
|
||||
cryptographers. Each kind of cryptographic primitive (i.e., a hash, a
|
||||
symmetric cipher, an asymmetric cipher, etc.) has a set of expected
|
||||
properties, many of which can only be discovered and proven by hand
|
||||
through a lot of hard work. Thus, to check the correctness of a
|
||||
cryptographic function, a best practice for Cryptol use is to encode
|
||||
as many of these properties as one can in Cryptol itself and use
|
||||
Cryptol's validation and verification capabilities, discussed
|
||||
later in~\autoref{cha:high-assur-progr}. For example, the fundamental
|
||||
property of most ciphers is that encryption and decryption are
|
||||
inverses of each other.
|
||||
|
||||
To check the correctness of an \emph{implementation} $I$ of a
|
||||
cryptographic function $C$ means that one must show that the
|
||||
implementation $I$ behaves as the specification ($C$) stipulates. In
|
||||
the context of cryptography, the minimal conformance necesssary is
|
||||
that $I$'s output \emph{exactly} conforms to the output characterized
|
||||
by $C$. But just because a cryptographic implementation is
|
||||
\emph{functionally correct} does not mean it is \emph{secure}. The
|
||||
subtleties of an implementation can leak all kinds of information that
|
||||
harm the security of the cryptography, including abstraction leaking
|
||||
of sensitive values, timing attacks, side-channel attacks, etc. These
|
||||
kinds of properties cannot currently be expressed or reasoned about in
|
||||
Cryptol.
|
||||
|
||||
Also, Cryptol does \emph{not} give the user any feedback on the
|
||||
\emph{strength} of a given (cryptographic) algorithm. While this is
|
||||
an interesting and useful feature, it is not part of Cryptol's current
|
||||
capabilities.
|
||||
|
||||
%=====================================================================
|
||||
\section{Caesar's cipher}
|
||||
\label{sec:caesar}
|
||||
\sectionWithAnswers{Caesar's cipher}{sec:caesar}
|
||||
|
||||
Caesar's cipher (a.k.a. Caesar's shift) is one of the simplest
|
||||
ciphers. The letters in the plaintext\indPlaintext are shifted by a
|
||||
fixed number of elements down the alphabet.\indCaesarscipher For
|
||||
instance, if the shift is 2, {\tt A} becomes {\tt C}, {\tt B} becomes
|
||||
{\tt D}, and so on. Once we run out of letters, we circle back to {\tt
|
||||
A}; so {\tt Y} becomes {\tt A}, and {\tt Z} becomes {\tt B}. Coding
|
||||
Caesar's cipher in Cryptol is quite straightforward (recall from
|
||||
Section~\ref{sec:tsyn} that a {\tt String n} is simply a sequence of n
|
||||
8-bit words.):\indTSString
|
||||
\begin{code}
|
||||
caesar : {n} ([8], String n) -> String n
|
||||
caesar (s, msg) = [ shift x | x <- msg ]
|
||||
where map = ['A' .. 'Z'] <<< s
|
||||
shift c = map @ (c - 'A')
|
||||
\end{code}
|
||||
In this definition, we simply get a message {\tt msg} of type {\tt
|
||||
String n}, and perform a {\tt shift} operation on each one of the
|
||||
elements. The {\tt shift} function is defined locally in the {\tt
|
||||
where}-clause.\indWhere To compute the shift, we first find the
|
||||
distance of the letter from the character {\tt 'A'} (via {\tt c -
|
||||
'A'}), and look it up in the mapping imposed by the shift. The {\tt
|
||||
map} is simply the alphabet rotated to the left by the shift amount,
|
||||
{\tt s}. Note how we use the enumeration {\tt ['A' .. 'Z']} to get all
|
||||
the letters in the alphabet.\indEnum
|
||||
|
||||
\begin{Exercise}\label{ex:caesar:0}
|
||||
What is the map corresponding to a shift of 2? Use Cryptol's
|
||||
\verb+<<<+\indRotLeft to compute it. You can use the command {\tt
|
||||
:set ascii=on}\indSettingASCII to print strings in ASCII, like
|
||||
this:
|
||||
\begin{Verbatim}
|
||||
Cryptol> :set ascii=on
|
||||
Cryptol> "Hello World"
|
||||
"Hello World"
|
||||
\end{Verbatim}
|
||||
Why do we use a left-rotate, instead of a right-rotate?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:caesar:0}
|
||||
Here is the alphabet and the corresponding shift-2 Caesar's alphabet:
|
||||
\begin{verbatim}
|
||||
Cryptol> ['A'..'Z']
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
Cryptol> ['A'..'Z'] <<< 2
|
||||
"CDEFGHIJKLMNOPQRSTUVWXYZAB"
|
||||
\end{verbatim}
|
||||
We use a left rotate to get the characters lined up correctly, as
|
||||
illustrated above. \indRotLeft\indRotRight
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:caesar:1}
|
||||
Use the above definition to encrypt the message {\tt "ATTACKATDAWN"}
|
||||
by shifts 0, 3, 12, and 52. What happens when the shift is a
|
||||
multiple of 26? Why?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:caesar:1}
|
||||
Here are Cryptol's responses:
|
||||
\begin{Verbatim}
|
||||
Cryptol> caesar (0, "ATTACKATDAWN")
|
||||
"ATTACKATDAWN"
|
||||
Cryptol> caesar (3, "ATTACKATDAWN")
|
||||
"DWWDFNDWGDZQ"
|
||||
Cryptol> caesar (12, "ATTACKATDAWN")
|
||||
"MFFMOWMFPMIZ"
|
||||
Cryptol> caesar (52, "ATTACKATDAWN")
|
||||
"ATTACKATDAWN"
|
||||
\end{Verbatim}
|
||||
If the shift is a multiple of 26 (as in 0 and 52 above), the letters
|
||||
will cycle back to their original values, so encryption will leave the
|
||||
message unchanged. Users of the Caesar's cipher should be careful
|
||||
about picking the shift amount!
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:caesar:2}
|
||||
Write a function {\tt dCaesar} which will decrypt a ciphertext
|
||||
constructed by a Caesar's cipher. It should have the same signature
|
||||
as {\tt caesar}. Try it on the examples from the previous exercise.
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:caesar:2}
|
||||
The code is almost identical, except we need to use a right
|
||||
rotate:\indRotRight
|
||||
|
||||
\begin{code}
|
||||
dCaesar : {n} ([8], String n) -> String n
|
||||
dCaesar (s, msg) = [ shift x | x <- msg ]
|
||||
where map = ['A' .. 'Z'] >>> s
|
||||
shift c = map @ (c - 'A')
|
||||
\end{code}
|
||||
% dCaesar : {n} ([8], String n) -> String n
|
||||
% dCaesar (s, msg) = [ shift x | x <- msg ]
|
||||
% where map = ['A' .. 'Z'] >>> s
|
||||
% shift c = map @ (c - 'A')
|
||||
We have:
|
||||
\begin{Verbatim}
|
||||
Cryptol> caesar (12, "ATTACKATDAWN")
|
||||
"MFFMOWMFPMIZ"
|
||||
Cryptol> dCaesar (12, "MFFMOWMFPMIZ")
|
||||
"ATTACKATDAWN"
|
||||
\end{Verbatim}
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:caesar:3}
|
||||
Observe that the shift amount in a Caesar cipher is very limited:
|
||||
Any shift of {\tt d} is equivalent to a shift by {\tt d \% 26}. (For
|
||||
instance shifting by 12 and 38 is the same thing, due to wrap around
|
||||
at 26.) Based on this observation, how strong do you think the
|
||||
Caesar's cipher is? Describe a simple attack that will recover the
|
||||
plaintext and automate it using Cryptol. Use your function to crack
|
||||
the ciphertext {\tt JHLZHYJPWOLYPZDLHR}.
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:caesar:3}
|
||||
For the Caesar's cipher, the only good shifts are $1$ through $25$,
|
||||
since shifting by $0$ would return the plaintext unchanged, and any
|
||||
shift amount {\tt d} that is larger than $26$ and over is essentially
|
||||
the same as shifting by {\tt d \% 26} due to wrap around. Therefore,
|
||||
all it takes to break the Caesar cipher is to try the sizes $1$
|
||||
through $25$, and see if we have a valid message. We can automate this
|
||||
in Cryptol by returning all possible plaintexts using these shift
|
||||
amounts:
|
||||
\begin{code}
|
||||
attackCaesar : {n} (String n) -> [25](String n)
|
||||
attackCaesar msg = [ dCaesar(i, msg) | i <- [1 .. 25] ]
|
||||
\end{code}
|
||||
If we apply this function to {\tt JHLZHYJPWOLYPZDLHR}, we get:
|
||||
\begin{Verbatim}
|
||||
Cryptol> :set ascii=on
|
||||
Cryptol> attackCaesar "JHLZHYJPWOLYPZDLHR",
|
||||
["IGKYGXIOVNKXOYCKGQ", "HFJXFWHNUMJWNXBJFP", "GEIWEVGMTLIVMWAIEO"
|
||||
"FDHVDUFLSKHULVZHDN", "ECGUCTEKRJGTKUYGCM", "DBFTBSDJQIFSJTXFBL"
|
||||
"CAESARCIPHERISWEAK", "BZDRZQBHOGDQHRVDZJ", "AYCQYPAGNFCPGQUCYI"
|
||||
"ZXBPXOZFMEBOFPTBXH", "YWAOWNYELDANEOSAWG", "XVZNVMXDKCZMDNRZVF"
|
||||
"WUYMULWCJBYLCMQYUE", "VTXLTKVBIAXKBLPXTD", "USWKSJUAHZWJAKOWSC"
|
||||
"TRVJRITZGYVIZJNVRB", "SQUIQHSYFXUHYIMUQA", "RPTHPGRXEWTGXHLTPZ"
|
||||
"QOSGOFQWDVSFWGKSOY", "PNRFNEPVCUREVFJRNX", "OMQEMDOUBTQDUEIQMW"
|
||||
"NLPDLCNTASPCTDHPLV", "MKOCKBMSZROBSCGOKU", "LJNBJALRYQNARBFNJT"
|
||||
"KIMAIZKQXPMZQAEMIS"]
|
||||
\end{Verbatim}
|
||||
If you skim through the potential ciphertexts, you will see that the
|
||||
$7^{th}$ entry is probably the one we are looking for. Hence the key
|
||||
must be $7$. Indeed, the message is {\tt CAESARCIPHERISWEAK}.
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:caesar:4}
|
||||
One classic trick to strengthen ciphers is to use multiple keys. By
|
||||
repeatedly encrypting the plaintext multiple times we can hope that
|
||||
it will be more resistant to attacks. Do you think this scheme might
|
||||
make the Caesar cipher stronger?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:caesar:4}
|
||||
No. Using two shifts $d_1$ and $d_2$ is essentially the same as
|
||||
using just one shift with the amount $d_1 + d_2$. Our attack
|
||||
function would work just fine on this schema as well. In fact, we
|
||||
wouldn't even have to know how many rounds of encryption was
|
||||
applied. Multiple rounds is just as weak as a single round when it
|
||||
comes to breaking the Caesar's cipher. \end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:caesar:5}
|
||||
What happens if you pass {\tt caesar} a plaintext that has
|
||||
non-uppercase letters in it? (Let's say a digit.) How can you fix
|
||||
this deficiency?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:caesar:5}
|
||||
In this case we will fail to find a mapping:
|
||||
\begin{Verbatim}
|
||||
Cryptol> caesar (3, "12")
|
||||
... index of 240 is out of bounds
|
||||
(valid range is 0 thru 25).
|
||||
\end{Verbatim}
|
||||
What happened here is that Cryptol computed the offset {\tt '1' - 'A'}
|
||||
to obtain the $8$-bit index $240$ (remember, modular arithmetic!), but
|
||||
our alphabet only has $26$ entries, causing the out-of-bounds error.
|
||||
\todo[inline]{Say something about how to guarantee that such errors
|
||||
are impossible. (Use of preconditions, checking and proving safety,
|
||||
etc.)} We can simply remedy this problem by allowing our alphabet
|
||||
to contain all $8$-bit numbers:\indRotLeft
|
||||
\begin{code}
|
||||
caesar' : {n} ([8], String n) -> String n
|
||||
caesar' (s, msg) = [ shift x | x <- msg ]
|
||||
where map = [0 .. 255] <<< s
|
||||
shift c = map @ c
|
||||
\end{code}
|
||||
Note that we no longer have to subtract {\tt 'A'}, since we are
|
||||
allowing a much wider range for our plaintext and ciphertext. (Another
|
||||
way to put this is that we are subtracting the value of the first
|
||||
element in the alphabet, which happens to be 0 in this case!
|
||||
Consequently, the number of ``good'' shifts increase from $25$ to
|
||||
$255$.) The change in {\tt dCaesar'} is analogous:\indRotRight
|
||||
\begin{code}
|
||||
dCaesar' : {n} ([8], String n) -> String n
|
||||
dCaesar' (s, msg) = [ shift x | x <- msg ]
|
||||
where map = [0 .. 255] >>> s
|
||||
shift c = map @ c
|
||||
\end{code}
|
||||
\end{Answer}
|
||||
|
||||
%=====================================================================
|
||||
\section{\texorpdfstring{Vigen\`{e}re}{Vigenere} cipher}
|
||||
\label{sec:vigenere}
|
||||
\sectionWithAnswers{\texorpdfstring{Vigen\`{e}re}{Vigenere} cipher}{sec:vigenere}
|
||||
|
||||
The Vigen\`{e}re cipher is a variation on the Caesar's cipher, where
|
||||
one uses multiple shift amounts according to a
|
||||
keyword~\cite{wiki:vigenere}.\indVigenere Despite its simplicity, it
|
||||
earned the notorious description {\em le chiffre ind\`{e}chiffrable}
|
||||
(``the indecipherable cipher'' in French), as it was unbroken for a
|
||||
long period of time. It was very popular in the 16th century and
|
||||
onwards, only becoming routinely breakable by mid-19th century or so.
|
||||
|
||||
To illustrate the operation of the Vigen\`{e}re cipher, let us
|
||||
consider the plaintext {\tt ATTACKATDAWN}. The cryptographer picks a
|
||||
key, let's say {\tt CRYPTOL}. We line up the plaintext and the key,
|
||||
repeating the key as much as as necessary, as in the top two lines of
|
||||
the following:
|
||||
\begin{tabbing}
|
||||
\hspace*{2cm} \= Ciphertext: \hspace*{.5cm} \= {\tt CKRPVYLVUYLG} \kill
|
||||
\> Plaintext : \> {\tt ATTACKATDAWN} \\
|
||||
\> Cipherkey : \> {\tt CRYPTOLCRYPT} \\
|
||||
\> Ciphertext: \> {\tt CKRPVYLVUYLG}
|
||||
\end{tabbing}
|
||||
We then proceed pair by pair, shifting the plaintext character by the
|
||||
distance implied by the corresponding key character. The first pair
|
||||
is {\tt A}-{\tt C}. Since {\tt C} is two positions away from {\tt A}
|
||||
in the alphabet, we shift {\tt A} by two positions, again obtaining
|
||||
{\tt C}. The second pair {\tt T}-{\tt R} proceeds similarly: Since
|
||||
{\tt R} is 17 positions away from {\tt A}, we shift {\tt T} down 17
|
||||
positions, wrapping around {\tt Z}, obtaining {\tt K}. Proceeding in
|
||||
this fashion, we get the ciphertext {\tt CKRPVYLVUYLG}. Note how each
|
||||
step of the process is a simple application of the Caesar's
|
||||
cipher.\indCaesarscipher
|
||||
|
||||
\begin{Exercise}\label{ex:vigenere:0}
|
||||
One component of the Vigen\`{e}re cipher is the construction of the
|
||||
repeated key. Write a function {\tt cycle} with the following
|
||||
signature:
|
||||
\begin{code}
|
||||
cycle : {n, a} (fin n, n >= 1) => [n]a -> [inf]a
|
||||
\end{code}
|
||||
such that it returns the input sequence appended to itself repeatedly,
|
||||
turning it into an infinite sequence. Why do we need the predicate
|
||||
{\tt n >= 1}?\indPredicates
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:vigenere:0}
|
||||
Here is one way to define {\tt cycle}, using a recursive definition:
|
||||
\begin{code}
|
||||
cycle xs = xss
|
||||
where xss = xs # xss
|
||||
\end{code}
|
||||
We have:
|
||||
\begin{Verbatim}
|
||||
Cryptol> cycle [1 .. 3]
|
||||
[1, 2, 3, 1, 2, ...]
|
||||
\end{Verbatim}
|
||||
If we do not have the {\tt n >= 1} predicate, then we can pass {\tt
|
||||
cycle} the empty sequence, which would cause an infinite loop
|
||||
emitting nothing. The predicate {\tt n >= 1} makes sure the input is
|
||||
non-empty, guaranteeing that {\tt cycle} can produce the infinite
|
||||
sequence.
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:vigenere:1}
|
||||
Program the Vigen\`{e}re cipher in Cryptol. It should have the
|
||||
signature:
|
||||
\begin{code}
|
||||
vigenere : {n, m} (fin n, n >= 1) => (String n, String m) -> String m
|
||||
\end{code}
|
||||
where the first argument is the key and the second is the
|
||||
plaintext. Note how the signature ensures that the input string and
|
||||
the output string will have precisely the same number of characters,
|
||||
{\tt m}. \lhint{Use Caesar's cipher repeatedly.}
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:vigenere:1}
|
||||
\begin{code}
|
||||
vigenere (key, pt) = join [ caesar (k - 'A', [c])
|
||||
| c <- pt
|
||||
| k <- cycle key
|
||||
]
|
||||
\end{code}
|
||||
Note the shift is determined by the distance from the letter {\tt 'A'}
|
||||
for each character. Here is the cipher in action:
|
||||
\begin{Verbatim}
|
||||
Cryptol> vigenere ("CRYPTOL", "ATTACKATDAWN")
|
||||
"CKRPVYLVUYLG"
|
||||
\end{Verbatim}
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:vigenere:2}
|
||||
Write the decryption routine for Vigen\`{e}re. Then decode \\
|
||||
{\tt "XZETGSCGTYCMGEQGAGRDEQC"} with the key {\tt "CRYPTOL"}.
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:vigenere:2}
|
||||
Following the lead of the encryption, we can rely on {\tt dCaesar}:
|
||||
\begin{code}
|
||||
dVigenere : {n, m} (fin n, n >= 1) =>
|
||||
(String n, String m) -> String m
|
||||
dVigenere (key, pt) = join [ dCaesar (k - 'A', [c])
|
||||
| c <- pt
|
||||
| k <- cycle key
|
||||
]
|
||||
\end{code}
|
||||
The secret code is:
|
||||
\begin{Verbatim}
|
||||
Cryptol> dVigenere ("CRYPTOL", "XZETGSCGTYCMGEQGAGRDEQC")
|
||||
"VIGENERECANTSTOPCRYPTOL"
|
||||
\end{Verbatim}
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:vigenere:3}
|
||||
A known-plaintext attack\indKnownPTAttack is one where an attacker
|
||||
obtains a plaintext-ciphertext pair, without the key. If the
|
||||
attacker can figure out the key based on this pair then he can break
|
||||
all subsequent communication until the key is replaced. Describe how
|
||||
one can break the Vigen\`{e}re cipher if a plaintext-ciphertext pair
|
||||
is known.
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:vigenere:3}
|
||||
All it takes is to decrypt using using the plaintext as the key and
|
||||
message as the cipherkey. Here is this process in action. Recall
|
||||
from the previous exercise that encrypting {\tt ATTACKATDAWN} by the
|
||||
key {\tt CRYPTOL} yields {\tt CKRPVYLVUYLG}. Now, if an attacker
|
||||
knows that {\tt ATTACKATDAWN} and {\tt CKRPVYLVUYLG} form a pair,
|
||||
he/she can find the key simply by:\indVigenere
|
||||
\begin{Verbatim}
|
||||
Cryptol> dVigenere ("ATTACKATDAWN", "CKRPVYLVUYLG")
|
||||
"CRYPTOLCRYPT"
|
||||
\end{Verbatim}
|
||||
Note that this process will not always tell us what the key is
|
||||
precisely. It will only be the key repeated for the given message
|
||||
size. For sufficiently large messages, or when the key does not repeat
|
||||
any characters, however, it would be really easy for an attacker to
|
||||
glean the actual key from this information.
|
||||
|
||||
This trick works since the act of using the plaintext as the key and
|
||||
the ciphertext as the message essentially reverses the shifting
|
||||
process, revealing the shift amounts for each pair of characters. The
|
||||
same attack would essentially work for the Caesar's cipher as well,
|
||||
where we would only need one character to crack it.\indCaesarscipher
|
||||
\end{Answer}
|
||||
|
||||
%%%% Way too complicated for the intro.. skipping for now
|
||||
%% \section{Rail fence cipher}
|
||||
%% \lable{sec:railfence}
|
||||
%% \sectionWithAnswers{Rail fence cipher}{sec:railfence}\indRailFence
|
||||
%% The $k$-rail fence cipher is a simple example of a transposition
|
||||
%% cipher\indTranspositioncipher, where the text is written along {\em
|
||||
%% k}-lines in a zig-zag fashion. For instance, to encrypt {\tt
|
||||
%% ATTACKATDAWN} using a 3-rail fence, we construct the following
|
||||
%% text:
|
||||
%% \begin{Verbatim}
|
||||
%% A . . . C . . . D . . .
|
||||
%% . T . A . K . T . A . N
|
||||
%% . . T . . . A . . . W .
|
||||
%% \end{Verbatim}
|
||||
%% going down and up the 3 fences in a zigzag fashion. We then read
|
||||
%% the ciphertext\indCiphertext line by line to obtain:
|
||||
%% \begin{Verbatim}
|
||||
%% ACDTAKTANTAW
|
||||
%% \end{Verbatim}
|
||||
%%
|
||||
%% \begin{Exercise}\label{ex:railfence:0}
|
||||
%% Program the 3-rail fence cipher in Cryptol. You should write the
|
||||
%% functions:
|
||||
%% \begin{code}
|
||||
%% rail3Fence, dRail3Fence : {a} (fin a) => String((4*a)) -> String ((4*a));
|
||||
%% \end{code}
|
||||
%% that implements the 3-rails encryption/decryption. Using your
|
||||
%% functions, encrypt and decrypt the message {\tt
|
||||
%% RAILFENCECIPHERISTRICKIERTHANITLOOKS}.
|
||||
%% \end{Exercise}
|
||||
%% \begin{Answer}\ansref{ex:railfence:0}
|
||||
%% \begin{code}
|
||||
%% rail3Fence pt = heads # mids # tails
|
||||
%% where {
|
||||
%% regions = groupBy (4, pt);
|
||||
%% heads = [| r @ 0 || r <- regions |];
|
||||
%% mids = join [| [(r @ 1) (r @ 3)] || r <- regions |];
|
||||
%% tails = [| r @ 2 || r <- regions |];
|
||||
%% };
|
||||
%% \end{code}
|
||||
%% \end{Answer}
|
||||
|
||||
%=====================================================================
|
||||
\section{The atbash}
|
||||
\label{sec:atbash}
|
||||
\sectionWithAnswers{The atbash}{sec:atbash}
|
||||
|
||||
The atbash cipher is a form of a shift cipher, where each letter is
|
||||
replaced by the letter that occupies its mirror image position in the
|
||||
alphabet.\indAtbash That is, {\tt A} is replaced by {\tt Z}, {\tt B}
|
||||
by {\tt Y}, etc. Needless to say the atbash is hardly worthy of
|
||||
cryptographic attention, as it is trivial to break.
|
||||
|
||||
\begin{Exercise}\label{ex:atbash:0}
|
||||
Program the atbash in Cryptol. What is the code for {\tt
|
||||
ATTACKATDAWN}?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:atbash:0}
|
||||
Using the reverse index operator, coding atbash is
|
||||
trivial:\indRIndex\indAtbash
|
||||
\begin{code}
|
||||
atbash : {n} String n -> String n
|
||||
atbash pt = [ alph ! (c - 'A') | c <- pt ]
|
||||
where alph = ['A' .. 'Z']
|
||||
\end{code}
|
||||
We have:
|
||||
\begin{Verbatim}
|
||||
Cryptol> atbash "ATTACKATDAWN"
|
||||
"ZGGZXPZGWZDM"
|
||||
\end{Verbatim}
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:atbash:1}
|
||||
Program the atbash decryption in Cryptol. Do you have to write any
|
||||
code at all? Break the code {\tt ZGYZHSRHHVOUWVXIBKGRMT}.
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:atbash:1}
|
||||
Notice that decryption for atbash\indAtbash is precisely the same as
|
||||
encryption, the process is entirely the same. So, we do not have to
|
||||
write any code at all, we can simply define:
|
||||
\begin{code}
|
||||
dAtbash : {n} String n -> String n
|
||||
dAtbash = atbash
|
||||
\end{code}
|
||||
We have:
|
||||
\begin{Verbatim}
|
||||
Cryptol> dAtbash "ZGYZHSRHHVOUWVXIBKGRMT"
|
||||
"ATBASHISSELFDECRYPTING"
|
||||
\end{Verbatim}
|
||||
\end{Answer}
|
||||
|
||||
%=====================================================================
|
||||
\section{Substitution ciphers}
|
||||
\label{section:subst}
|
||||
\sectionWithAnswers{Substitution ciphers}{section:subst}
|
||||
|
||||
Substitution ciphers\indSubstitutioncipher generalize all the ciphers
|
||||
we have seen so far, by allowing arbitrary substitutions to be made
|
||||
for individual ``components'' of the
|
||||
plaintext~\cite{wiki:substitution}. Note that these components need
|
||||
not be individual characters, but rather can be pairs or even triples
|
||||
of characters that appear consecutively in the text. (The
|
||||
multi-character approach is termed {\em
|
||||
polygraphic}.)\indPolyGraphSubst Furthermore, there are variants
|
||||
utilizing multiple {\em polyalphabetic} mappings,\indPolyAlphSubst as
|
||||
opposed to a single {\em monoalphabetic} mapping\indMonoAlphSubst. We
|
||||
will focus on monoalphabetic simple substitutions, although the other
|
||||
variants are not fundamentally more difficult to implement.
|
||||
|
||||
\tip{For the exercises in this section we will use a running key
|
||||
repeatedly. To simplify your interaction with Cryptol, put the
|
||||
following definition in your program file:}
|
||||
\begin{code}
|
||||
substKey : String 26
|
||||
substKey = "FJHWOTYRXMKBPIAZEVNULSGDCQ"
|
||||
\end{code}
|
||||
The intention is that {\tt substKey} maps {\tt A} to {\tt F}, {\tt B}
|
||||
to {\tt J}, {\tt C} to {\tt H}, and so on.
|
||||
|
||||
\begin{Exercise}\label{ex:subst:0}
|
||||
Implement substitution ciphers in Cryptol. Your function should have
|
||||
the signature:
|
||||
\begin{code}
|
||||
subst : {n} (String 26, String n) -> String n
|
||||
\end{code}
|
||||
where the first element is the key (like {\tt substKey}).
|
||||
What is the code for \\
|
||||
{\tt "SUBSTITUTIONSSAVETHEDAY"} for the key {\tt substKey}?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:subst:0}
|
||||
\begin{code}
|
||||
subst (key, pt) = [ key @ (p - 'A') | p <- pt ]
|
||||
\end{code}
|
||||
We have:
|
||||
\begin{Verbatim}
|
||||
Cryptol> subst(substKey, "SUBSTITUTIONSSAVETHEDAY")
|
||||
"NLJNUXULUXAINNFSOUROWFC"
|
||||
\end{Verbatim}
|
||||
\end{Answer}
|
||||
|
||||
\paragraph*{Decryption} Programming decryption is more subtle. We can
|
||||
no longer use the simple selection operation ({\tt @})\indIndex on the
|
||||
key. Instead, we have to search for the character that maps to the
|
||||
given ciphertext character.
|
||||
|
||||
\begin{Exercise}\label{ex:subst:1}
|
||||
Write a function {\tt invSubst} with the following signature:
|
||||
%% type Char = [8] // now in prelude.cry
|
||||
\begin{code}
|
||||
invSubst : (String 26, Char) -> Char
|
||||
\end{code}
|
||||
such that it returns the mapped plaintext character. For instance,
|
||||
with {\tt substKey}, {\tt F} should get you {\tt A}, since the key
|
||||
maps {\tt A} to {\tt F}:
|
||||
\begin{Verbatim}
|
||||
Cryptol> invSubst (substKey, 'F')
|
||||
A
|
||||
\end{Verbatim}
|
||||
And similarly for other examples:
|
||||
\begin{Verbatim}
|
||||
Cryptol> invSubst (substKey, 'J')
|
||||
B
|
||||
Cryptol> invSubst (substKey, 'C')
|
||||
Y
|
||||
Cryptol> invSubst (substKey, 'Q')
|
||||
Z
|
||||
\end{Verbatim}
|
||||
One question is what happens if you search for a non-existing
|
||||
character. In this case you can just return {\tt 0}, a non-valid
|
||||
ASCII character, which can be interpreted as {\em not found}.
|
||||
\hint{Use a fold (see Pg.~\pageref{par:fold}).}\indFold
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:subst:1}
|
||||
\begin{code}
|
||||
invSubst (key, c) = candidates ! 0
|
||||
where candidates = [0] # [ if c == k then a else p
|
||||
| k <- key
|
||||
| a <- ['A' .. 'Z']
|
||||
| p <- candidates
|
||||
]
|
||||
\end{code}
|
||||
The comprehension\indComp defining {\tt candidates} uses a fold (see
|
||||
page~\pageref{par:fold}).\indFold The first branch ({\tt k <- key})
|
||||
walks through all the key elements, the second branch walks through
|
||||
the ordinary alphabet ({\tt a <- ['A' .. 'Z']}), and the final branch
|
||||
walks through the candidate match so far. At the end of the fold, we
|
||||
simply return the final element of {\tt candidates}. Note that we
|
||||
start with {\tt 0} as the first element, so that if no match is found
|
||||
we get a {\tt 0} back.
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:subst:2}
|
||||
Using {\tt invSubst}, write the decryption function {\tt dSubst}.
|
||||
It should have the exact same signature as {\tt subst}. Decrypt
|
||||
{\tt FUUFHKFUWFGI}, using our running key.
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:subst:2}
|
||||
\begin{code}
|
||||
dSubst: {n} (String 26, String n) -> String n
|
||||
dSubst (key, ct) = [ invSubst (key, c) | c <- ct ]
|
||||
\end{code}
|
||||
We have:
|
||||
\begin{Verbatim}
|
||||
Cryptol> dSubst (substKey, "FUUFHKFUWFGI")
|
||||
"ATTACKATDAWN"
|
||||
\end{Verbatim}
|
||||
\end{Answer}
|
||||
|
||||
\todo[inline]{This exercise and the true type of \texttt{invSubst}
|
||||
indicate that specs are needed. In other words, we cannot capture
|
||||
\texttt{invSubst}'s tightest type, which would encode the invariant
|
||||
about contents being capital letters, and that lack of
|
||||
expressiveness leaks to \texttt{dSubst}. We really need to either
|
||||
enrich the dependent types or add some kind of support for
|
||||
contracts. The reason this works most of the time is that crypto
|
||||
algorithms work on arbitrary bytes.}
|
||||
|
||||
\begin{Exercise}\label{ex:subst:3}
|
||||
Try the substitution cipher with the key {\tt
|
||||
AAAABBBBCCCCDDDDEEEEFFFFGG}. Does it still work? What is special
|
||||
about {\tt substKey}?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:subst:3}
|
||||
No, with this key we cannot decrypt properly:
|
||||
\begin{Verbatim}
|
||||
Cryptol> subst ("AAAABBBBCCCCDDDDEEEEFFFFGG", "HELLOWORLD")
|
||||
"BBCCDFDECA"
|
||||
Cryptol> dSubst ("AAAABBBBCCCCDDDDEEEEFFFFGG", "BBCCDFDECA")
|
||||
"HHLLPXPTLD"
|
||||
\end{Verbatim}
|
||||
This is because the given key maps multiple plaintext letters to the
|
||||
same ciphertext letter. (For instance, it maps all of {\tt A}, {\tt
|
||||
B}, {\tt C}, and {\tt D} to the letter {\tt A}.) For substitution
|
||||
ciphers to work the key should not repeat the elements, providing a
|
||||
1-to-1 mapping. This property clearly holds for {\tt substKey}. Note
|
||||
that there is no shortage of keys, since for 26 letters we have 26!
|
||||
possible ways to choose keys, which gives us over 4-billion different
|
||||
choices.
|
||||
\end{Answer}
|
||||
|
||||
%=====================================================================
|
||||
\section{The scytale}
|
||||
\label{sec:scytale}
|
||||
\sectionWithAnswers{The scytale}{sec:scytale}
|
||||
|
||||
The scytale is one of the oldest cryptographic devices ever, dating
|
||||
back to at least the first century
|
||||
A.D.~\cite{wiki:scytale}.\indScytale Ancient Greeks used a leather
|
||||
strip on which they would write their plaintext\indPlaintext message.
|
||||
The strip would be wrapped around a rod of a certain diameter. Once
|
||||
the strip is completely wound, they would read the text row-by-row,
|
||||
essentially transposing the letters and constructing the
|
||||
ciphertext\indCiphertext. Since the ciphertext is formed by a
|
||||
rearrangement of the plaintext, the scytale is an example of a
|
||||
transposition cipher.\indTranspositioncipher To decrypt, the
|
||||
ciphertext needs to be wrapped around a rod of the same diameter,
|
||||
reversing the process. The cipherkey\indCipherkey is essentially the
|
||||
diameter of the rod used. Needless to say, the scytale does not
|
||||
provide a very strong encryption mechanism.
|
||||
|
||||
Abstracting away from the actual rod and the leather strip, encryption
|
||||
is essentially writing the message column-by-column in a matrix and
|
||||
reading it row-by-row. Let us illustrate with the message {\tt
|
||||
ATTACKATDAWN}, where we can fit 4 characters per column:
|
||||
\begin{verbatim}
|
||||
ACD
|
||||
TKA
|
||||
TAW
|
||||
ATN
|
||||
\end{verbatim}
|
||||
To encrypt, we read the message row-by-row, obtaining {\tt
|
||||
ACDTKATAWATN}. If the message does not fit properly (i.e., if it has
|
||||
empty spaces in the last column), it can be padded by {\tt Z}'s or
|
||||
some other agreed upon character. To decrypt, we essentially reverse
|
||||
the process, by writing the ciphertext row-by-row and reading it
|
||||
column-by-column.
|
||||
|
||||
Notice how the scytale's operation is essentially matrix
|
||||
transposition. Therefore, implementing the scytale in Cryptol is
|
||||
merely an application of the {\tt transpose} function.\indTranspose
|
||||
All we need to do is group the message by the correct number of
|
||||
elements using {\tt split}.\indSplit Below, we define the {\tt
|
||||
diameter} to be the number of columns we have. The type synonym {\tt
|
||||
Message} ensures we only deal with strings that properly fit the
|
||||
``rod,'' by using {\tt r} number of rows:\indJoin
|
||||
|
||||
\begin{code}
|
||||
scytale : {row, diameter} (fin row, fin diameter)
|
||||
=> String (row * diameter) -> String (diameter * row)
|
||||
scytale msg = join (transpose msg')
|
||||
where msg' : [diameter][row][8]
|
||||
msg' = split msg
|
||||
\end{code}
|
||||
The signature\indSignature on {\tt msg'} is revealing: We are taking a
|
||||
string that has {\tt diameter * row} characters in it, and chopping it
|
||||
up so that it has {\tt row} elements, each of which is a string that
|
||||
has {\tt diameter} characters in it. Here is Cryptol in action,
|
||||
encrypting the message {\tt ATTACKATDAWN}:
|
||||
\begin{Verbatim}
|
||||
Cryptol> :set ascii=on
|
||||
Cryptol> scytale "ATTACKATDAWN"
|
||||
"ACDTKATAWATN"
|
||||
\end{Verbatim}
|
||||
Decryption is essentially the same process, except we have to {\tt
|
||||
split} so that we get {\tt diameter} elements
|
||||
out:\indSplit\indJoin\indScytale
|
||||
\begin{code}
|
||||
dScytale : {row, diameter} (fin row, fin diameter)
|
||||
=> String (row * diameter) -> String (diameter * row)
|
||||
dScytale msg = join (transpose msg')
|
||||
where msg' : [row][diameter][8]
|
||||
msg' = split msg
|
||||
\end{code}
|
||||
Again, the type on {\tt msg'} tells Cryptol that we now want {\tt
|
||||
diameter} strings, each of which is {\tt row} long. It is important
|
||||
to notice that the definitions of {\tt scytale} and {\tt dScytale} are
|
||||
precisely the same, except for the signature on {\tt msg'}! When
|
||||
viewed as a matrix, the types precisely tell which transposition we
|
||||
want at each step. We have:
|
||||
\begin{Verbatim}
|
||||
Cryptol> dScytale "ACDTKATAWATN"
|
||||
"ATTACKATDAWN"
|
||||
\end{Verbatim}
|
||||
|
||||
\begin{Exercise}\label{ex:scytale:0}
|
||||
What happens if you comment out the signature for {\tt msg'} in the
|
||||
definition of {\tt scytale}? Why?\indScytale
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:scytale:0}
|
||||
If you do not provide a signature for {\tt msg'}, you will get the
|
||||
following type-error message from Cryptol:
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
Failed to validate user-specified signature.
|
||||
In the definition of 'scytale', at classic.cry:40:1--40:8:
|
||||
for any type row, diameter
|
||||
fin row
|
||||
fin diameter
|
||||
=>
|
||||
fin ?b
|
||||
arising from use of expression split at classic.cry:42:17--42:22
|
||||
fin ?d
|
||||
arising from use of expression join at classic.cry:40:15--40:19
|
||||
row * diameter == ?a * ?b
|
||||
arising from matching types at classic.cry:1:1--1:1
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
Essentially, Cryptol is complaining that it was asked to do a {\tt
|
||||
split}\indSplit and it figured that the constraint
|
||||
$\text{\emph{diameter}}*\text{\emph{row}}=a*b$ must hold, but that is
|
||||
not sufficient to determine what {\tt a} and {\tt b} should really
|
||||
be. (There could be multiple ways to assign {\tt a} and {\tt b} to
|
||||
satisfy that requirement, for instance {\tt a=4}, {\tt b=row}; or {\tt
|
||||
a=2} and {\tt b=2*row}, resulting in differing behavior.) This is
|
||||
why it is unable to ``validate the user-specified signature''. By
|
||||
putting the explicit signature for {\tt msg'}, we are giving Cryptol
|
||||
more information to resolve the ambiguity. Notice that since the code
|
||||
for {\tt scytale} and {\tt dScytale} are precisely the same except for
|
||||
the type on {\tt msg'}. This is a clear indication that the type
|
||||
signature plays an essential role here.\indAmbiguity\indSignature
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:scytale:1}
|
||||
How would you attack a scytale encryption, if you don't know what
|
||||
the diameter is?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:scytale:1}
|
||||
Even if we do not know the diameter, we do know that it is a divisor
|
||||
of the length of the message. For any given message size, we can
|
||||
compute the number of divisors of the size and try decryption until
|
||||
we find a meaningful plaintext. Of course, the number of potential
|
||||
divisors will be large for large messages, but the practicality of
|
||||
scytale stems from the choice of relatively small diameters, hence
|
||||
the search would not take too long. (With large diameters, the
|
||||
ancient Greeks would have to carry around very thick rods, which
|
||||
would not be very practical in a battle scenario!)\indScytale
|
||||
\end{Answer}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
9
docs/ProgrammingCryptol/conclusion/Conclusion.tex
Normal file
9
docs/ProgrammingCryptol/conclusion/Conclusion.tex
Normal file
@ -0,0 +1,9 @@
|
||||
\chapter{Conclusion}
|
||||
\label{cha:conclusion}
|
||||
|
||||
To be written.
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
BIN
docs/ProgrammingCryptol/cover/Blank.pdf
Normal file
BIN
docs/ProgrammingCryptol/cover/Blank.pdf
Normal file
Binary file not shown.
BIN
docs/ProgrammingCryptol/cover/Cover.pdf
Normal file
BIN
docs/ProgrammingCryptol/cover/Cover.pdf
Normal file
Binary file not shown.
BIN
docs/ProgrammingCryptol/cover/Cryptol1Cover.pdf
Normal file
BIN
docs/ProgrammingCryptol/cover/Cryptol1Cover.pdf
Normal file
Binary file not shown.
4835
docs/ProgrammingCryptol/cover/CryptolCover.ai
Normal file
4835
docs/ProgrammingCryptol/cover/CryptolCover.ai
Normal file
File diff suppressed because one or more lines are too long
4912
docs/ProgrammingCryptol/cover/CryptolSmallCover.ai
Normal file
4912
docs/ProgrammingCryptol/cover/CryptolSmallCover.ai
Normal file
File diff suppressed because one or more lines are too long
2146
docs/ProgrammingCryptol/cover/CryptolSmallCover.pdf
Normal file
2146
docs/ProgrammingCryptol/cover/CryptolSmallCover.pdf
Normal file
File diff suppressed because one or more lines are too long
BIN
docs/ProgrammingCryptol/cover/Cryptol_cover_template.gif
Executable file
BIN
docs/ProgrammingCryptol/cover/Cryptol_cover_template.gif
Executable file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
BIN
docs/ProgrammingCryptol/cover/Cryptol_teardrop.png
Executable file
BIN
docs/ProgrammingCryptol/cover/Cryptol_teardrop.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
docs/ProgrammingCryptol/cover/Cryptol_teardrop.white.PNG
Executable file
BIN
docs/ProgrammingCryptol/cover/Cryptol_teardrop.white.PNG
Executable file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
4954
docs/ProgrammingCryptol/cover/ProgrammingCryptolCover.ai
Normal file
4954
docs/ProgrammingCryptol/cover/ProgrammingCryptolCover.ai
Normal file
File diff suppressed because one or more lines are too long
4954
docs/ProgrammingCryptol/cover/ProgrammingCryptolCover.pdf
Normal file
4954
docs/ProgrammingCryptol/cover/ProgrammingCryptolCover.pdf
Normal file
File diff suppressed because one or more lines are too long
3049
docs/ProgrammingCryptol/crashCourse/CrashCourse.tex
Normal file
3049
docs/ProgrammingCryptol/crashCourse/CrashCourse.tex
Normal file
File diff suppressed because it is too large
Load Diff
BIN
docs/ProgrammingCryptol/crashCourse/streamDiagram.pdf
Normal file
BIN
docs/ProgrammingCryptol/crashCourse/streamDiagram.pdf
Normal file
Binary file not shown.
BIN
docs/ProgrammingCryptol/crashCourse/streamExercise.pdf
Normal file
BIN
docs/ProgrammingCryptol/crashCourse/streamExercise.pdf
Normal file
Binary file not shown.
16
docs/ProgrammingCryptol/des/DES.tex
Normal file
16
docs/ProgrammingCryptol/des/DES.tex
Normal file
@ -0,0 +1,16 @@
|
||||
\commentout{
|
||||
\begin{code}
|
||||
module DES where
|
||||
|
||||
\end{code}
|
||||
}
|
||||
|
||||
\chapter{DES: The Data Encryption Standard}
|
||||
\label{cha:des:-data-encryption}
|
||||
|
||||
\todo[inline]{Move content from DES writeup here.}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
1
docs/ProgrammingCryptol/enigma/.gitignore
vendored
Normal file
1
docs/ProgrammingCryptol/enigma/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/auto
|
148
docs/ProgrammingCryptol/enigma/Enigma.cry
Normal file
148
docs/ProgrammingCryptol/enigma/Enigma.cry
Normal file
@ -0,0 +1,148 @@
|
||||
// Cryptol Enigma Simulator
|
||||
// Copyright (c) 2010-2013, Galois Inc.
|
||||
// www.cryptol.net
|
||||
// You can freely use this source code for educational purposes.
|
||||
|
||||
// Helper synonyms:
|
||||
// type Char = [8]
|
||||
module Enigma where
|
||||
|
||||
type Permutation = String 26
|
||||
|
||||
// Enigma components:
|
||||
type Plugboard = Permutation
|
||||
type Rotor = [26](Char, Bit)
|
||||
type Reflector = Permutation
|
||||
|
||||
// An enigma machine with n rotors:
|
||||
type Enigma n = { plugboard : Plugboard,
|
||||
rotors : [n]Rotor,
|
||||
reflector : Reflector
|
||||
}
|
||||
|
||||
// Check membership in a sequence:
|
||||
elem : {a, b} (fin 0, fin a, Cmp b) => (b, [a]b) -> Bit
|
||||
elem (x, xs) = matches ! 0
|
||||
where matches = [False] # [ m || (x == e) | e <- xs
|
||||
| m <- matches
|
||||
]
|
||||
// Inverting a permutation lookup:
|
||||
invSubst : (Permutation, Char) -> Char
|
||||
invSubst (key, c) = candidates ! 0
|
||||
where candidates = [0] # [ if c == k then a else p
|
||||
| k <- key
|
||||
| a <- ['A' .. 'Z']
|
||||
| p <- candidates
|
||||
]
|
||||
|
||||
// Constructing a rotor
|
||||
mkRotor : {n} (fin n) => (Permutation, String n) -> Rotor
|
||||
mkRotor (perm, notchLocations) = [ (p, elem (p, notchLocations))
|
||||
| p <- perm
|
||||
]
|
||||
|
||||
// Action of a single rotor on a character
|
||||
// Note that we encrypt and then rotate, if necessary
|
||||
scramble : (Bit, Char, Rotor) -> (Bit, Char, Rotor)
|
||||
scramble (rotate, c, rotor) = (notch, c', rotor')
|
||||
where
|
||||
(c', _) = rotor @ (c - 'A')
|
||||
(_, notch) = rotor @ 0
|
||||
rotor' = if rotate then rotor <<< 1 else rotor
|
||||
|
||||
// Connecting rotors in a sequence
|
||||
joinRotors : {n} (fin n) => ([n]Rotor, Char) -> ([n]Rotor, Char)
|
||||
joinRotors (rotors, inputChar) = (rotors', outputChar)
|
||||
where
|
||||
initRotor = mkRotor (['A' .. 'Z'], [])
|
||||
ncrs : [n+1](Bit, [8], Rotor)
|
||||
ncrs = [(True, inputChar, initRotor)]
|
||||
# [ scramble (notch, char, r)
|
||||
| r <- rotors
|
||||
| (notch, char, rotor') <- ncrs
|
||||
]
|
||||
rotors' = tail [ r | (_, _, r) <- ncrs ]
|
||||
(_, outputChar, _) = ncrs ! 0
|
||||
|
||||
// Following the signal through a single rotor, forward and backward
|
||||
substFwd, substBwd : (Permutation, Char) -> Char
|
||||
substFwd (perm, c) = perm @ (c - 'A')
|
||||
substBwd (perm, c) = invSubst (perm, c)
|
||||
// Route the signal back from the reflector, chase through rotors
|
||||
backSignal : {n} (fin n) => ([n]Rotor, Char) -> Char
|
||||
backSignal (rotors, inputChar) = cs ! 0
|
||||
where cs = [inputChar] # [ substBwd ([ p | (p, _) <- r ], c)
|
||||
| r <- reverse rotors
|
||||
| c <- cs
|
||||
]
|
||||
|
||||
// The full enigma loop, from keyboard to lamps:
|
||||
// The signal goes through the plugboard, rotors, and the reflector,
|
||||
// then goes back through the sequence in reverse, out of the
|
||||
// plugboard and to the lamps
|
||||
enigmaLoop : {n} (fin n) => (Plugboard, [n]Rotor, Reflector, Char) -> ([n]Rotor, Char)
|
||||
enigmaLoop (pboard, rotors, refl, c0) = (rotors', c5)
|
||||
where
|
||||
c1 = substFwd (pboard, c0)
|
||||
(rotors', c2) = joinRotors (rotors, c1)
|
||||
c3 = substFwd (refl, c2)
|
||||
c4 = backSignal(rotors, c3)
|
||||
c5 = substBwd (pboard, c4)
|
||||
|
||||
// Construct a machine out of parts
|
||||
mkEnigma : {n} (Plugboard, [n]Rotor, Reflector, [n]Char) -> Enigma n
|
||||
mkEnigma (pboard, rs, refl, startingPositions) =
|
||||
{ plugboard = pboard
|
||||
, rotors = [ r <<< (s - 'A')
|
||||
| r <- rs
|
||||
| s <- startingPositions
|
||||
]
|
||||
, reflector = refl
|
||||
}
|
||||
|
||||
// Encryption/Decryption
|
||||
enigma : {n, m} (fin n, fin m) => (Enigma n, String m) -> String m
|
||||
enigma (m, pt) = tail [ c | (_, c) <- rcs ]
|
||||
where rcs = [(m.rotors, '*')] #
|
||||
[ enigmaLoop (m.plugboard, r, m.reflector, c)
|
||||
| c <- pt
|
||||
| (r, _) <- rcs
|
||||
]
|
||||
|
||||
// Decryption is the same as encryption:
|
||||
// dEnigma : {n, m} (fin n, fin m) => (Enigma n, String m) -> String m
|
||||
dEnigma = enigma
|
||||
|
||||
|
||||
// Build an example enigma machine:
|
||||
plugboard : Plugboard
|
||||
plugboard = "HBGDEFCAIJKOWNLPXRSVYTMQUZ"
|
||||
|
||||
rotor1, rotor2, rotor3 : Rotor
|
||||
rotor1 = mkRotor ("RJICAWVQZODLUPYFEHXSMTKNGB", "IO")
|
||||
rotor2 = mkRotor ("DWYOLETKNVQPHURZJMSFIGXCBA", "B")
|
||||
rotor3 = mkRotor ("FGKMAJWUOVNRYIZETDPSHBLCQX", "CK")
|
||||
|
||||
reflector : Reflector
|
||||
reflector = "FEIPBATSCYVUWZQDOXHGLKMRJN"
|
||||
|
||||
modelEnigma : Enigma 3
|
||||
modelEnigma = mkEnigma (plugboard, [rotor1, rotor2, rotor3], reflector, "GCR")
|
||||
|
||||
/* Example run:
|
||||
|
||||
cryptol> :set ascii=on
|
||||
cryptol> enigma (modelEnigma, "ENIGMAWASAREALLYCOOLMACHINE")
|
||||
UPEKTBSDROBVTUJGNCEHHGBXGTF
|
||||
cryptol> dEnigma (modelEnigma, "UPEKTBSDROBVTUJGNCEHHGBXGTF")
|
||||
ENIGMAWASAREALLYCOOLMACHINE
|
||||
*/
|
||||
|
||||
all: {a, n} (fin n) => (a->Bit) -> [n]a -> Bit
|
||||
all fn xs = folds ! 0 where
|
||||
folds = [True] # [ fn x && p | x <- xs
|
||||
| p <- folds]
|
||||
checkReflectorFwdBwd : Reflector -> Bit
|
||||
checkReflectorFwdBwd refl = all check ['A' .. 'Z']
|
||||
where check c = substFwd (refl, c) == substBwd (refl, c)
|
||||
|
774
docs/ProgrammingCryptol/enigma/Enigma.tex
Normal file
774
docs/ProgrammingCryptol/enigma/Enigma.tex
Normal file
@ -0,0 +1,774 @@
|
||||
\chapter{The Enigma machine}
|
||||
\label{chapter:enigma}
|
||||
|
||||
The Enigma machine is probably the most famous of all cryptographic
|
||||
devices in history, due to the prominent role it played in
|
||||
WWII~\cite{wiki:enigma}.\indEnigma The first Enigma machines were
|
||||
available around 1920s, with various models in the market for
|
||||
commercial use. When Germans used the Enigma during WWII, they were
|
||||
using a particular model referred to as the {\em Wehrmacht Enigma}, a
|
||||
fairly advanced model available at the time.
|
||||
|
||||
The most important role of Enigma\indEnigma is in its role in the use
|
||||
of automated machines to aid in secret communication, or what is known
|
||||
as \emph{mechanizing secrecy}. One has to understand that computers
|
||||
as we understand them today were not available when Enigma was in
|
||||
operation. Thus, the Enigma employed a combination of mechanical
|
||||
(keyboard, rotors, etc.) and electrical parts (lamps, wirings, etc.)
|
||||
to implement its functionality. However, our focus in this chapter
|
||||
will not be on the mechanical aspects of Enigma at all. For a highly
|
||||
readable account of that, we refer the reader to Singh's excellent
|
||||
book on cryptography~\cite{Singh:1999:CBE}. Instead, we will model
|
||||
Enigma in Cryptol in an algorithmic sense, implementing Enigma's
|
||||
operations without any reference to the underlying mechanics. More
|
||||
precisely, we will model an Enigma machine that has a plugboard, three
|
||||
interchangeable scramblers, and a fixed reflector.
|
||||
|
||||
\todo[inline]{Add a photo or two of some Enigmas here. Look into the
|
||||
WikiCommons.}
|
||||
|
||||
\todo[inline]{Provide an architectural diagram of this Cryptol
|
||||
construction somewhere reasonable and refer to it regularly to give
|
||||
the reader a better big-picture of how the spec hangs together
|
||||
vs.~the actual machine.}
|
||||
|
||||
%=====================================================================
|
||||
\section{The plugboard}
|
||||
\label{sec:enigma:plugboard}
|
||||
\sectionWithAnswers{The plugboard}{sec:enigma:plugboard}
|
||||
|
||||
Enigma essentially implements a polyalphabetic substitution cipher
|
||||
(Section~\ref{section:subst})\indPolyAlphSubst, consisting of a number
|
||||
of rotating units that jumble up the alphabet. The first component is
|
||||
the so called plugboard ({\em steckerbrett} in
|
||||
German)\indEnigmaPlugboard. In the original Enigma, the plugboard
|
||||
provided a means of interchanging 6-pairs or letters. For instance,
|
||||
the plugboard could be set-up so that pressing the {\tt B} key would
|
||||
actually engage the {\tt Q} key, etc. We will slightly generalize and
|
||||
allow any number of pairings, as we are not limited by the
|
||||
availability of cables or actual space to put them in a box! Viewed in
|
||||
this sense, the plugboard is merely a permutation of the alphabet. In
|
||||
Cryptol, we can represent the plugboard combination by a string of 26
|
||||
characters, corresponding to the pairings for each letter in the
|
||||
alphabet from {\tt A} to {\tt Z}:
|
||||
|
||||
\begin{code}
|
||||
type Permutation = String 26
|
||||
type Plugboard = Permutation
|
||||
\end{code}
|
||||
For instance, the plugboard matching the pairs {\tt A}-{\tt H}, {\tt
|
||||
C}-{\tt G}, {\tt Q}-{\tt X}, {\tt T}-{\tt V}, {\tt U}-{\tt Y}, {\tt
|
||||
W}-{\tt M}, and {\tt O}-{\tt L} can be created as follows:
|
||||
\begin{code}
|
||||
plugboard : Plugboard
|
||||
plugboard = "HBGDEFCAIJKOWNLPXRSVYTMQUZ"
|
||||
\end{code}
|
||||
Note that if a letter is not paired through the plugboard, then it
|
||||
goes untouched, i.e., it is paired with itself.
|
||||
|
||||
\begin{Exercise}\label{ex:enigma:1}
|
||||
Use Cryptol to verify that the above plugboard definition indeed
|
||||
implements the pairings we wanted.
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:enigma:1}
|
||||
We can simply ask Cryptol what the implied mappings are:
|
||||
\begin{Verbatim}
|
||||
Cryptol> [ plugboard @ (c - 'A') | c <- "ACQTUWO" ]
|
||||
"HGXVYML"
|
||||
\end{Verbatim}
|
||||
Why do we subtract the {\tt 'A'} when indexing?
|
||||
\end{Answer}
|
||||
|
||||
\note{In Enigma, the plugboard pairings are symmetric; if {\tt A} maps
|
||||
to {\tt H}, then {\tt H} must map to {\tt A}.}
|
||||
|
||||
%=====================================================================
|
||||
\section{Scrambler rotors}
|
||||
\label{sec:enigma:scramblerrotors}
|
||||
\sectionWithAnswers{Scrambler rotors}{sec:enigma:scramblerrotors}
|
||||
|
||||
The next component of the Enigma are the rotors that scramble the
|
||||
letters. Rotors ({\em walzen} in German)\indEnigmaRotor are
|
||||
essentially permutations, with one little twist: as their name
|
||||
implies, they rotate. This rotation ensures that the next character
|
||||
the rotor will process will be encrypted using a different alphabet,
|
||||
thus giving Enigma its polyalphabetic nature.\indPolyAlphSubst
|
||||
|
||||
The other trick employed by Enigma is how the rotations are done. In a
|
||||
typical setup, the rotors are arranged so that the first rotor rotates
|
||||
at every character, while the second rotates at every 26th, the third
|
||||
at every 676th ($=26*26$), etc. In a sense, the rotors work like the
|
||||
odometer in your car, one full rotation of the first rotor triggers
|
||||
the second, whose one full rotation triggers the third, and so on. In
|
||||
fact, more advanced models of Enigma allowed for two notches per
|
||||
rotor, i.e., two distinct positions on the rotor that will allow the
|
||||
next rotor in sequence to rotate itself. We will allow ourselves to
|
||||
have any number of notches, by simply pairing each substituted letter
|
||||
with a bit value saying whether it has an associated notch:
|
||||
\footnote{The type definition for {\tt Char} was given in
|
||||
Example~\ref{section:subst}-\ref{ex:subst:1}.}
|
||||
|
||||
\begin{code}
|
||||
type Rotor = [26](Char, Bit)
|
||||
\end{code}
|
||||
The function {\tt mkRotor} will create a rotor for us from a given permutation of the letters and the notch
|
||||
locations:~\footnote{The function {\tt elem} was defined in Exercise~\ref{sec:recandrec}-\ref{ex:recfun:4:1}.\indElem}
|
||||
\begin{code}
|
||||
mkRotor : {n} (fin n) => (Permutation, String n) -> Rotor
|
||||
mkRotor (perm, notchLocations) = [ (p, elem (p, notchLocations))
|
||||
| p <- perm
|
||||
]
|
||||
\end{code}
|
||||
\todo[inline]{A diagram here would be really useful, especially one
|
||||
that captures the location and use of notches and the state of these
|
||||
rotors before and after rotations.}
|
||||
Let us create a couple of rotors with notches:
|
||||
\begin{code}
|
||||
rotor1, rotor2, rotor3 : Rotor
|
||||
rotor1 = mkRotor ("RJICAWVQZODLUPYFEHXSMTKNGB", "IO")
|
||||
rotor2 = mkRotor ("DWYOLETKNVQPHURZJMSFIGXCBA", "B")
|
||||
rotor3 = mkRotor ("FGKMAJWUOVNRYIZETDPSHBLCQX", "CK")
|
||||
\end{code}
|
||||
For instance, {\tt rotor1} maps {\tt A} to {\tt R}, {\tt B} to {\tt J},
|
||||
$\ldots$, and {\tt Z} to {\tt B} in its initial position. It will engage its
|
||||
notch if one of the permuted letters {\tt I} or {\tt O} appear in its first
|
||||
position.
|
||||
|
||||
\begin{Exercise}\label{ex:enigma:2}
|
||||
Write out the encrypted letters for the sequence of 5 {\tt C}'s for
|
||||
{\tt rotor1}, assuming it rotates in each step. At what points does
|
||||
it engage its own notch to signal the next rotor to rotate?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:enigma:2}
|
||||
Recall that {\tt rotor1} was defined as:
|
||||
\begin{Verbatim}
|
||||
rotor1 = mkRotor ("RJICAWVQZODLUPYFEHXSMTKNGB", "IO")
|
||||
\end{Verbatim}
|
||||
Here is a listing of the new mappings and the characters we will get
|
||||
at the output for each successive {\tt C}:
|
||||
\begin{Verbatim}
|
||||
starting map output notch engaged?
|
||||
RJICAWVQZODLUPYFEHXSMTKNGB I no
|
||||
JICAWVQZODLUPYFEHXSMTKNGBR C no
|
||||
ICAWVQZODLUPYFEHXSMTKNGBRJ A yes
|
||||
CAWVQZODLUPYFEHXSMTKNGBRJI W no
|
||||
AWVQZODLUPYFEHXSMTKNGBRJIC V no
|
||||
\end{Verbatim}
|
||||
Note how we get different letters as output, even though we are
|
||||
providing the same input (all {\tt C}'s.) This is the essence of the
|
||||
Enigma: the same input will not cause the same output necessarily,
|
||||
making it a polyalphabetic substitution cipher.\indPolyAlphSubst
|
||||
\end{Answer}
|
||||
|
||||
%=====================================================================
|
||||
\section{Connecting the rotors: notches in action}
|
||||
\label{sec:enigma:notches}
|
||||
\sectionWithAnswers{Connecting the rotors: notches in action}{sec:enigma:notches}
|
||||
|
||||
\todo[inline]{A diagram here depicting rotor interchangeability and
|
||||
the relationship between \texttt{scramble} and rotors in the above
|
||||
figure.}
|
||||
|
||||
The original Enigma had three interchangeable rotors. The operator
|
||||
chose the order they were placed in the machine. In our model, we will
|
||||
allow for an arbitrary number of rotors. The tricky part of connecting
|
||||
the rotors is ensuring that the rotations of each are done properly.
|
||||
|
||||
Let us start with a simpler problem. If we are given a rotor and a
|
||||
particular letter to encrypt, how can we compute the output letter and
|
||||
the new rotor position? First of all, we will need to know if the
|
||||
rotor should rotate itself, that is if the notch between this rotor
|
||||
and the previous one was activated. Also, we need to find out if the
|
||||
act of rotation in this rotor is going to cause the next rotor to
|
||||
rotate. We will model this action using the Cryptol function {\tt
|
||||
scramble}:
|
||||
\begin{code}
|
||||
scramble : (Bit, Char, Rotor) -> (Bit, Char, Rotor)
|
||||
\end{code}
|
||||
The function {\tt scramble} takes a triple \texttt{(rotate, c, rotor)}:
|
||||
\begin{itemize}
|
||||
\item {\tt rotate}: if {\tt True}, this rotor will rotate before
|
||||
encryption. Indicates that the notch between this rotor and the
|
||||
previous one was engaged,
|
||||
\item {\tt c}: the character to encrypt, and
|
||||
\item {\tt rotor}: the current state of the rotor.
|
||||
\end{itemize}
|
||||
Similarly, the output will also be a triple:
|
||||
\begin{itemize}
|
||||
\item {\tt notch}: {\tt True} if the notch on this rotor engages,
|
||||
i.e., if the next rotor should rotate itself,
|
||||
\item {\tt c'}: the result of encrypting (substituting) for {\tt c}
|
||||
with the current state of the rotor.
|
||||
\item {\tt rotor'}: the new state of the rotor. If no rotation was
|
||||
done this will be the same as {\tt rotor}. Otherwise it will be the
|
||||
new substitution map obtained by rotating the old one to the left by
|
||||
one.
|
||||
\end{itemize}
|
||||
Coding {\tt scramble} is straightforward:
|
||||
\begin{code}
|
||||
scramble (rotate, c, rotor) = (notch, c', rotor')
|
||||
where
|
||||
(c', _) = rotor @ (c - 'A')
|
||||
(_, notch) = rotor @ 0
|
||||
rotor' = if rotate then rotor <<< 1 else rotor
|
||||
\end{code}
|
||||
To determine {\tt c'}, we use the substitution map to find out what
|
||||
this rotor maps the given character to, with respect to its current
|
||||
state. Note how Cryptol's pattern matching notation\indPatMatch helps
|
||||
with extraction of {\tt c'}, as we only need the character, not
|
||||
whether there is a notch at that location. (The underscore character
|
||||
use, `\texttt{\_}',\indUnderscore means that we do not need the value
|
||||
at the position, and hence we do not give it an explicit name.) To
|
||||
determine if we have our notch engaged, all we need to do is to look
|
||||
at the first elements notch value, using Cryptol's selection operator
|
||||
({\tt @ 0}\indIndex), and we ignore the permutation value there this
|
||||
time, again using pattern matching. Finally, to determine {\tt
|
||||
rotor'} we merely rotate-left by 1\indRotLeft if the {\tt rotate}
|
||||
signal was received. Otherwise, we leave the {\tt rotor} unchanged.
|
||||
|
||||
\begin{Exercise}\label{ex:enigma:3}
|
||||
Redo Exercise~\ref{ex:enigma:2}, this time using Cryptol and the
|
||||
{\tt scramble} function.
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:enigma:3}
|
||||
We can define the following value to simulate the operation of
|
||||
always telling {\tt scramble} to rotate the rotor and providing it
|
||||
with the input {\tt C}.
|
||||
\begin{Verbatim}
|
||||
rotor1CCCCC = [(c1, n1), (c2, n2), (c3, n3), (c4, n4), (c5, n5)]
|
||||
where (n1, c1, r1) = scramble (True, 'C', rotor1)
|
||||
(n2, c2, r2) = scramble (True, 'C', r1)
|
||||
(n3, c3, r3) = scramble (True, 'C', r2)
|
||||
(n4, c4, r4) = scramble (True, 'C', r3)
|
||||
(n5, c5, r5) = scramble (True, 'C', r4)
|
||||
\end{Verbatim}
|
||||
\todo[inline]{Remind reader of simultaneity of \texttt{where}
|
||||
clauses.} Note how we chained the output rotor values in the calls,
|
||||
through the values {\tt r1}-{\tt r2}-{\tt r3} and {\tt r4}. We have:
|
||||
\begin{Verbatim}
|
||||
Cryptol> rotor1CCCCC
|
||||
[(I, False), (C, False), (A, True), (W, False), (V, False)]
|
||||
\end{Verbatim}
|
||||
Note that we get precisely the same results from Cryptol as we
|
||||
predicted in the previous exercise.
|
||||
\end{Answer}
|
||||
|
||||
\note{The actual mechanics of the Enigma machine were slightly more
|
||||
complicated: due to the keyboard mechanism and the way notches were
|
||||
mechanically built, the first rotor was actually rotating before the
|
||||
encryption took place. Also, the middle rotor could double-step if
|
||||
it engages its notch right after the third rotor
|
||||
does~\cite{enigmaAnomaly}.
|
||||
|
||||
We will take the simpler view here and assume that each key press
|
||||
causes an encryption to take place, {\em after} which the rotors do
|
||||
their rotation, getting ready for the next input. The mechanical
|
||||
details, while historically important, are not essential for our
|
||||
modeling purposes here. Also, the original Enigma had {\em rings}, a
|
||||
relatively insignificant part of the whole machine, that we ignore
|
||||
here.}
|
||||
|
||||
\paragraph*{Sequencing the rotors} Now that we have the rotors modeled,
|
||||
the next task is to figure out how to connect them in a sequence. As
|
||||
we mentioned, Enigma had 3 rotors originally (later versions allowing
|
||||
4). The three rotors each had a single notch (later versions allowing
|
||||
double notches). Our model allows for arbitrary number of rotors and
|
||||
arbitrary number of notches on each. The question we now tackle is
|
||||
the following: Given a sequence of rotors, how do we run them one
|
||||
after the other? We are looking for a function with the following
|
||||
signature:
|
||||
\begin{code}
|
||||
joinRotors : {n} (fin n) => ([n]Rotor, Char) -> ([n]Rotor, Char)
|
||||
\end{code}
|
||||
That is, we receive {\tt n} rotors and the character to be encrypted,
|
||||
and return the updated rotors (accounting for their rotations) and the
|
||||
final character. The implementation is an instance of the
|
||||
fold\indFold pattern (Section~\ref{sec:recandrec}), using the {\tt
|
||||
scramble} function we have just defined:
|
||||
\begin{code}
|
||||
joinRotors (rotors, inputChar) = (rotors', outputChar)
|
||||
where
|
||||
initRotor = mkRotor (['A' .. 'Z'], [])
|
||||
ncrs : [n+1](Bit, [8], Rotor)
|
||||
ncrs = [(True, inputChar, initRotor)]
|
||||
# [ scramble (notch, char, r)
|
||||
| r <- rotors
|
||||
| (notch, char, rotor') <- ncrs
|
||||
]
|
||||
rotors' = tail [ r | (_, _, r) <- ncrs ]
|
||||
(_, outputChar, _) = ncrs ! 0
|
||||
\end{code}
|
||||
The workhorse in {\tt joinRotors} is the definition of {\tt ncrs}, a
|
||||
mnemonic for {\em notches-chars-rotors}. The idea is fairly simple.
|
||||
We simply iterate over all the given rotors ({\tt r <- rotors}), and
|
||||
{\tt scramble} the current character {\tt char}, using the rotor {\tt
|
||||
r} and the notch value {\tt notch}. These values come from {\tt
|
||||
ncrs} itself, using the fold pattern\indFold encoded by the
|
||||
comprehension\indComp. The only question is what is the seed value
|
||||
for this fold?
|
||||
|
||||
The seed used in {\tt ncrs} is {\tt (True, inputChar, initRotor)}. The
|
||||
first component is {\tt True}, indicating that the very first rotor
|
||||
should always rotate itself at every step. The second element is {\tt
|
||||
inputChar}, which is the input to the whole sequence of rotors. The
|
||||
only mysterious element is the last one, which we have specified as
|
||||
{\tt initRotor}. This rotor is defined so that it simply maps the
|
||||
letters to themselves with no notches on it, by a call to the {\tt
|
||||
mkRotor} function we have previously defined. This rotor is merely a
|
||||
place holder to kick off the computation of {\tt ncrs}, it acts as the
|
||||
identity element in a sequence of rotors. To compute {\tt rotors'},
|
||||
we merely project the third component of {\tt ncrs}, being careful
|
||||
about skipping the first element using {\tt tail}\indTail. Finally,
|
||||
{\tt outputChar} is merely the output coming out of the final rotor,
|
||||
extracted using {\tt !0}\indRIndex. Note how we use Cryptol's pattern
|
||||
matching to get the second component out of the triple in the last
|
||||
line.\indPatMatch
|
||||
|
||||
\begin{Exercise}\label{ex:enigma:4}
|
||||
Is the action of {\tt initRotor} ever used in the definition of {\tt
|
||||
joinRotors}?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:enigma:4}
|
||||
Not unless we receive an empty sequence of rotors, i.e., a call of
|
||||
the form: {\tt joinRotors ([], c)} for some character {\tt c}. In
|
||||
this case, it does make sense to return {\tt c} directly, which is
|
||||
what {\tt initRotor} will do. Note that unless we do receive an
|
||||
empty sequence of rotors, the value of {\tt initRotor} will not be
|
||||
used when computing the {\tt joinRotors} function.
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:enigma:5}
|
||||
What is the final character returned by the expression:
|
||||
\begin{Verbatim}
|
||||
joinRotors ([rotor1 rotor2 rotor3], 'F')
|
||||
\end{Verbatim}
|
||||
Use paper and pencil to figure out the answer by tracing the execution
|
||||
of {\tt joinRotors} before running it in Cryptol!
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:enigma:5}
|
||||
The crucial part is the value of {\tt ncrs}. Let us write it out by
|
||||
substituting the values of {\tt rotors} and {\tt inputChar}:
|
||||
\begin{Verbatim}
|
||||
ncrs = [(True, 'F', initRotor)]
|
||||
# [ scramble (notch, char, r)
|
||||
| r <- [rotor1, rotor2, rotor3]
|
||||
| (notch, char, rotor') <- ncrs
|
||||
]
|
||||
\end{Verbatim}
|
||||
Clearly, the first element of {\tt ncrs} will be:
|
||||
\begin{Verbatim}
|
||||
(True, 'F', initRotor)
|
||||
\end{Verbatim}
|
||||
Therefore, the second element will be the result of the call:
|
||||
\begin{Verbatim}
|
||||
scramble (True, 'F', rotor1)
|
||||
\end{Verbatim}
|
||||
Recall that {\tt rotor1} was defined as:
|
||||
\begin{Verbatim}
|
||||
rotor1 = mkRotor ("RJICAWVQZODLUPYFEHXSMTKNGB", "IO")
|
||||
\end{Verbatim}
|
||||
What letter does {\tt rotor1} map {\tt F} to? Since {\tt F} is the 5th
|
||||
character (counting from 0), {\tt rotor1} maps it to the 5th element
|
||||
of its permutation, i.e., {\tt W}, remembering to count from 0! The
|
||||
topmost element in {\tt rotor1} is {\tt R}, which is not its
|
||||
notch-list, hence it will {\em not} tell the next rotor to rotate. But
|
||||
it will rotate itself, since it received the {\tt True} signal. Thus,
|
||||
the second element of {\tt ncrs} will be:
|
||||
\begin{Verbatim}
|
||||
(False, 'W', ...)
|
||||
\end{Verbatim}
|
||||
where we used {\tt ...} to denote the one left-rotation of {\tt
|
||||
rotor1}. (Note that we do not need to know the precise arrangement
|
||||
of {\tt rotor1} now for the purposes of this exercise.) Now we move to
|
||||
{\tt rotor2}, we have to compute the result of the call:
|
||||
\begin{Verbatim}
|
||||
scramble (False, 'W', rotor2)
|
||||
\end{Verbatim}
|
||||
Recall that {\tt rotor2} was defined as:
|
||||
\begin{Verbatim}
|
||||
rotor2 = mkRotor ("DWYOLETKNVQPHURZJMSFIGXCBA", "B")
|
||||
\end{Verbatim}
|
||||
So, it maps {\tt W} to {\tt X}. (The fourth letter from the end.) It
|
||||
will not rotate itself, and it will not tell {\tt rotor3} to rotate
|
||||
itself either since the topmost element is {\tt D} in its current
|
||||
configuration, and {\tt D} which is not in the notch-list {\tt
|
||||
"B"}. Thus, the final {\tt scramble} call will be:
|
||||
\begin{Verbatim}
|
||||
scramble (False, 'X', rotor3)
|
||||
\end{Verbatim}
|
||||
where
|
||||
\begin{Verbatim}
|
||||
rotor3 = mkRotor ("FGKMAJWUOVNRYIZETDPSHBLCQX", "CK")
|
||||
\end{Verbatim}
|
||||
It is easy to see that {\tt rotor3} will map {\tt X} to {\tt C}. Thus
|
||||
the final value coming out of this expression must be {\tt C}. Indeed,
|
||||
we have:\indTupleProj
|
||||
\begin{Verbatim}
|
||||
Cryptol> project(2, 2, joinRotors ([rotor1 rotor2 rotor3], 'F'))
|
||||
C
|
||||
\end{Verbatim}
|
||||
Of course, Cryptol also keeps track of the new rotor positions as
|
||||
well, which we have glossed over in this discussion.
|
||||
\end{Answer}
|
||||
|
||||
%=====================================================================
|
||||
\section{The reflector}
|
||||
\label{sec:enigma:reflector}
|
||||
\sectionWithAnswers{The reflector}{sec:enigma:reflector}
|
||||
|
||||
The final piece of the Enigma machine is the
|
||||
reflector\indEnigmaReflector ({\em umkehrwalze} in German). The
|
||||
reflector is another substitution map. Unlike the rotors, however, the
|
||||
reflector did not rotate. Its main function was ensuring that the
|
||||
process of encryption was reversible: The reflector did one final
|
||||
jumbling of the letters and then sent the signal back through the
|
||||
rotors in the {\em reverse} order, thus completing the loop and
|
||||
allowing the signal to reach back to the lamps that would light up.
|
||||
For our purposes, it suffices to model it just like any other
|
||||
permutation:
|
||||
\begin{code}
|
||||
type Reflector = Permutation
|
||||
\end{code}
|
||||
Here is one example:
|
||||
\begin{code}
|
||||
reflector : Reflector
|
||||
reflector = "FEIPBATSCYVUWZQDOXHGLKMRJN"
|
||||
\end{code}
|
||||
Like the plugboard, the reflector is symmetric: If it maps {\tt B} to
|
||||
{\tt E}, it should map {\tt E} to {\tt B}, as in the above
|
||||
example. Furthermore, the Enigma reflectors were designed so that they
|
||||
never mapped any character to themselves, which is true for the above
|
||||
permutation as well. Interestingly, this idea of a non-identity
|
||||
reflector (i.e., never mapping any character to itself) turned out to
|
||||
be a weakness in the design, which the allies exploited in breaking
|
||||
the Enigma during WWII~\cite{Singh:1999:CBE}.
|
||||
|
||||
\begin{Exercise}\label{ex:enigma:6}
|
||||
Write a function {\tt checkReflector} with the signature:
|
||||
\begin{Verbatim}
|
||||
checkReflector : Reflector -> Bit
|
||||
\end{Verbatim}
|
||||
such that it returns {\tt True} if a given reflector is good (i.e.,
|
||||
symmetric and non-self mapping) and {\tt False} otherwise. Check that
|
||||
our definition of {\tt reflector} above is a good one. \lhint{Use the
|
||||
{\tt all} function you have defined in
|
||||
Exercise~\ref{sec:zero}-\ref{ex:zero:1}.}
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:enigma:6}
|
||||
%% if this is {code} we have two all's
|
||||
\begin{Verbatim}
|
||||
all : {n, a} (fin n) => (a -> Bit) -> [n]a -> Bit
|
||||
all f xs = [ f x | x <- xs ] == ~zero
|
||||
|
||||
checkReflector refl = all check ['A' .. 'Z']
|
||||
where check c = (c != m) && (c == c')
|
||||
where m = refl @ (c - 'A')
|
||||
c' = refl @ (m - 'A')
|
||||
\end{Verbatim}
|
||||
For each character in the alphabet, we first figure out what it maps
|
||||
to using the reflector, named {\tt m} above. We also find out what
|
||||
{\tt m} gets mapped to, named {\tt c'} above. To be a valid reflector
|
||||
it must hold that {\tt c} is not {\tt m} (no character maps to
|
||||
itself), and {\tt c} must be {\tt c'}. We have:
|
||||
\begin{Verbatim}
|
||||
Cryptol> checkReflector reflector
|
||||
True
|
||||
\end{Verbatim}
|
||||
Note how we used {\tt all}\indAll to make sure {\tt check} holds for
|
||||
all the elements of the alphabet.
|
||||
\end{Answer}
|
||||
|
||||
%=====================================================================
|
||||
\section{Putting the pieces together}
|
||||
\label{sec:enigma:puttingittogether}
|
||||
\sectionWithAnswers{Putting the pieces together}{sec:enigma:puttingittogether}
|
||||
|
||||
We now have all the components of the Enigma: the plugboard, rotors,
|
||||
and the reflector. The final task is to implement the full loop. The
|
||||
Enigma ran all the rotors in sequence, then passed the signal through
|
||||
the reflector, and ran the rotors in reverse one more time before
|
||||
delivering the signal to the lamps.
|
||||
|
||||
Before proceeding, we will define the following two helper functions:
|
||||
\begin{code}
|
||||
substFwd, substBwd : (Permutation, Char) -> Char
|
||||
substFwd (perm, c) = perm @ (c - 'A')
|
||||
substBwd (perm, c) = invSubst (perm, c)
|
||||
\end{code}
|
||||
(You have defined the {\tt invSubst} function in
|
||||
Exercise~\ref{section:subst}-\ref{ex:subst:1}.) The {\tt substFwd}
|
||||
function simply returns the character that the given permutation,
|
||||
whether from the plugboard, a rotor, or the reflector. Conversely,
|
||||
{\tt substBwd} returns the character that the given permutation maps
|
||||
{\em from}, i.e., the character that will be mapped to {\tt c} using
|
||||
the permutation.
|
||||
|
||||
\begin{Exercise}\label{ex:enigma:7}
|
||||
Using Cryptol, verify that {\tt substFwd} and {\tt substBwd} return
|
||||
the same elements for each letter in the alphabet for {\tt rotor1}.
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:enigma:7}
|
||||
We can define the following helper function, using the function {\tt
|
||||
all} you have defined in
|
||||
Exercise~\ref{sec:zero}-\ref{ex:zero:1}:\indAll
|
||||
\begin{code}
|
||||
checkPermutation : Permutation -> Bit
|
||||
checkPermutation perm = all check ['A' .. 'Z']
|
||||
where check c = (c == substBwd(perm, substFwd (perm, c)))
|
||||
&& (c == substFwd(perm, substBwd (perm, c)))
|
||||
\end{code}
|
||||
Note that we have to check both ways (first {\tt substFwd} then {\tt
|
||||
substBwd}, and also the other way around) in case the substitution
|
||||
is badly formed, for instance if it is mapping the same character
|
||||
twice. We have:
|
||||
\begin{Verbatim}
|
||||
Cryptol> checkPermutation [ c | (c, _) <- rotor1 ]
|
||||
True
|
||||
\end{Verbatim}
|
||||
For a bad permutation we would get {\tt False}:
|
||||
\begin{Verbatim}
|
||||
Cryptol> checkPermutation (['A' .. 'Y'] # ['A'])
|
||||
False
|
||||
\end{Verbatim}
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:enigma:8}
|
||||
Show that {\tt substFwd} and {\tt substBwd} are exactly the same
|
||||
operations for the reflector. Why?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:enigma:8}
|
||||
Since the reflector is symmetric, substituting backwards or forwards
|
||||
does not matter. We can verify this with the following helper
|
||||
function:\indAll
|
||||
\begin{code}
|
||||
all : {a, b} (fin b) => (a -> Bit) -> [b]a -> Bit
|
||||
all fn xs = folds ! 0 where
|
||||
folds = [True] # [ fn x && p | x <- xs
|
||||
| p <- folds]
|
||||
checkReflectorFwdBwd : Reflector -> Bit
|
||||
checkReflectorFwdBwd refl = all check ['A' .. 'Z']
|
||||
where check c = substFwd (refl, c) == substBwd (refl, c)
|
||||
\end{code}
|
||||
We have:
|
||||
\begin{Verbatim}
|
||||
Cryptol> checkReflectorFwdBwd reflector
|
||||
True
|
||||
\end{Verbatim}
|
||||
\end{Answer}
|
||||
|
||||
\paragraph*{The route back} One crucial part of the Enigma is the
|
||||
running of the rotors in reverse after the reflector. Note that this
|
||||
operation ignores the notches, i.e., the rotors do not turn while the
|
||||
signal is passing the second time through the rotors. (In a sense, the
|
||||
rotations happen after the signal completes its full loop, getting to
|
||||
the reflector and back.) Consequently, it is much easer to code as
|
||||
well (compare this code to {\tt joinRotors}, defined in
|
||||
Section~\ref{sec:enigma:notches}):
|
||||
|
||||
\begin{code}
|
||||
backSignal : {n} (fin n) => ([n]Rotor, Char) -> Char
|
||||
backSignal (rotors, inputChar) = cs ! 0
|
||||
where
|
||||
cs = [inputChar] # [ substBwd ([ p | (p, _) <- r ], c)
|
||||
| r <- reverse rotors
|
||||
| c <- cs
|
||||
]
|
||||
\end{code}
|
||||
Note that we explicitly reverse the rotors in the definition of {\tt
|
||||
cs}.\indReverse (The definition of {\tt cs} is another typical
|
||||
example of a fold. See Pg.~\pageref{par:fold}.)\indFold
|
||||
|
||||
Given all this machinery, coding the entire Enigma loop is fairly
|
||||
straightforward:
|
||||
\begin{code}
|
||||
//enigmaLoop : {n} (fin n) => (Plugboard, [n]Rotor, Reflector, Char)
|
||||
// -> ([n]Rotor, Char)
|
||||
enigmaLoop (pboard, rotors, refl, c0) = (rotors', c5)
|
||||
where
|
||||
// 1. First run through the plugboard
|
||||
c1 = substFwd (pboard, c0)
|
||||
// 2. Now run all the rotors forward
|
||||
(rotors', c2) = joinRotors (rotors, c1)
|
||||
// 3. Pass through the reflector
|
||||
c3 = substFwd (refl, c2)
|
||||
// 4. Run the rotors backward
|
||||
c4 = backSignal(rotors, c3)
|
||||
// 5. Finally, back through the plugboard
|
||||
c5 = substBwd (pboard, c4)
|
||||
\end{code}
|
||||
|
||||
%=====================================================================
|
||||
\section{The state of the machine}
|
||||
\label{sec:state-machine}
|
||||
|
||||
We are almost ready to construct our own Enigma machine in
|
||||
Cryptol. Before doing so, we will take a moment to represent the state
|
||||
of the Enigma machine as a Cryptol record\indTheRecordType, which will
|
||||
simplify our final construction. At any stage, the state of an Enigma
|
||||
machine is given by the status of its rotors. We will use the
|
||||
following record to represent this state, for an Enigma machine
|
||||
containing $n$ rotors:
|
||||
\begin{code}
|
||||
type Enigma n = { plugboard : Plugboard,
|
||||
rotors : [n]Rotor,
|
||||
reflector : Reflector
|
||||
}
|
||||
\end{code}
|
||||
To initialize an Enigma machine, the operator provides the plugboard
|
||||
settings, rotors, the reflector. Furthermore, the operator also gives
|
||||
the initial positions for the rotors. Rotors can be initially rotated
|
||||
to any position before put together into the machine. We can capture
|
||||
this operation with the function {\tt mkEnigma}:
|
||||
\begin{code}
|
||||
mkEnigma : {n} (Plugboard, [n]Rotor, Reflector, [n]Char)
|
||||
-> Enigma n
|
||||
mkEnigma (pboard, rs, refl, startingPositions) =
|
||||
{ plugboard = pboard,
|
||||
rotors = [ r <<< (s - 'A')
|
||||
| r <- rs
|
||||
| s <- startingPositions
|
||||
],
|
||||
reflector = refl
|
||||
}
|
||||
\end{code}
|
||||
Note how we rotate each given rotor to the left by the amount given by
|
||||
its starting position.
|
||||
|
||||
\todo[inline]{Connect ``left'' with up/down in the earlier
|
||||
illustrations.}
|
||||
|
||||
Given this definition, let us construct an Enigma machine out of the
|
||||
components we have created so far, using the starting positions {\tt
|
||||
GCR} for the rotors respectively:\label{def:modelEnigma}
|
||||
\begin{code}
|
||||
modelEnigma : Enigma 3
|
||||
modelEnigma = mkEnigma (plugboard, [rotor1, rotor2, rotor3],
|
||||
reflector, "GCR")
|
||||
\end{code}
|
||||
We now have an operational Enigma machine coded up in Cryptol!
|
||||
|
||||
%=====================================================================
|
||||
\section{Encryption and decryption}
|
||||
\label{enigma:encdec}
|
||||
\sectionWithAnswers{Encryption and decryption}{enigma:encdec}
|
||||
|
||||
Equipped with all the machinery we now have, coding Enigma encryption
|
||||
is fairly straightforward:
|
||||
\begin{code}
|
||||
enigma : {n, m} (fin n, fin m) => (Enigma n, String m) -> String m
|
||||
enigma (m, pt) = tail [ c | (_, c) <- rcs ]
|
||||
where rcs = [(m.rotors, '*')] #
|
||||
[ enigmaLoop (m.plugboard, r, m.reflector, c)
|
||||
| c <- pt
|
||||
| (r, _) <- rcs
|
||||
]
|
||||
\end{code}
|
||||
The function {\tt enigma} takes a machine with {\tt n} rotors and a
|
||||
plaintext of {\tt m} characters, returning a ciphertext of {\tt m}
|
||||
characters back. It is yet another application of the fold pattern,
|
||||
where we start with the initial set of rotors and the placeholder
|
||||
character {\tt *} (which could be anything) to seed the fold.\indFold
|
||||
Note how the change in rotors is reflected in each iteration of the
|
||||
fold, through the {\tt enigmaLoop} function. At the end, we simply
|
||||
drop the rotors from {\tt rcs}, and take the {\tt tail}\indTail to
|
||||
skip over the seed character {\tt *}.
|
||||
|
||||
Here is our Enigma in operation:
|
||||
\begin{Verbatim}
|
||||
Cryptol> :set ascii=on
|
||||
Cryptol> enigma (modelEnigma, "ENIGMAWASAREALLYCOOLMACHINE")
|
||||
"UPEKTBSDROBVTUJGNCEHHGBXGTF"
|
||||
\end{Verbatim}
|
||||
|
||||
\paragraph*{Decryption} As we mentioned before, Enigma was a
|
||||
self-decrypting machine, that is, encryption and decryption are
|
||||
precisely the same operations. Thus, we can define:
|
||||
\begin{code}
|
||||
dEnigma : {n, m} (fin n, fin m) => (Enigma n, String m) -> String m
|
||||
dEnigma = enigma
|
||||
\end{code}
|
||||
And decrypt our above message back:
|
||||
\begin{Verbatim}
|
||||
Cryptol> dEnigma (modelEnigma, "UPEKTBSDROBVTUJGNCEHHGBXGTF")
|
||||
"ENIGMAWASAREALLYCOOLMACHINE"
|
||||
\end{Verbatim}
|
||||
We have successfully performed our first Enigma encryption!
|
||||
|
||||
\begin{Exercise}\label{ex:enigma:9}
|
||||
Different models of Enigma came with different sets of rotors. You
|
||||
can find various rotor configurations on the
|
||||
web~\cite{wiki:enigmarotors}. Create models of these rotors in
|
||||
Cryptol, and run sample encryptions through them.
|
||||
\end{Exercise}
|
||||
|
||||
\begin{Exercise}\label{ex:enigma:10}
|
||||
As we have mentioned before, Enigma implements a polyalphabetic
|
||||
substitution cipher\indPolyAlphSubst, where the same letter gets
|
||||
mapped to different letters during encryption. The
|
||||
period\indSubstPeriod of a cipher is the number of characters before
|
||||
the encryption repeats itself, mapping the same sequence of letters
|
||||
in the plaintext to the to the same sequence of letters in the
|
||||
ciphertext. What is the period of an Enigma machine with $n$ rotors?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:enigma:10}
|
||||
Enigma will start repeating once the rotors go back to their
|
||||
original position. With $n$ rotors, this will take $26^n$
|
||||
characters. In the case of the traditional 3-rotor Enigma this
|
||||
amounts to $26^3 = 17576$ characters. Note that we are assuming an
|
||||
ideal Enigma here with no double-stepping~\cite{enigmaAnomaly}.
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:enigma:11}
|
||||
Construct a string of the form {\tt CRYPTOLXXX...XCRYPTOL}, where
|
||||
...'s are filled with enough number of {\tt X}'s such that
|
||||
encrypting it with our {\tt modelEnigma} machine will map the
|
||||
instances of ``{\tt CRYPTOL}'' to the same ciphertext. How many {\tt
|
||||
X}'s do you need? What is the corresponding ciphertext for ``{\tt
|
||||
CRYPTOL}'' in this encryption?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:enigma:11}
|
||||
Since the period\indSubstPeriod for the 3-rotor Enigma is 17576 (see
|
||||
the previous exercise), we need to make sure two instances of {\tt
|
||||
CRYPTOL} are 17576 characters apart. Since {\tt CRYPTOL} has 7
|
||||
characters, we should have 17569 X's. The following Cryptol
|
||||
definition would return the relevant pieces:
|
||||
\begin{code}
|
||||
enigmaCryptol = (take`{7} ct, drop`{17576} ct)
|
||||
where str = "CRYPTOL" # [ 'X' | _ <- [1 .. 17569] ]
|
||||
# "CRYPTOL"
|
||||
ct = dEnigma(modelEnigma, str)
|
||||
\end{code}
|
||||
We have:
|
||||
\begin{Verbatim}
|
||||
Cryptol> enigmaCryptol
|
||||
("KGSHMPK", "KGSHMPK")
|
||||
\end{Verbatim}
|
||||
As predicted, both instances of {\tt CRYPTOL} get encrypted as {\tt
|
||||
KGSHMPK}.
|
||||
\end{Answer}
|
||||
|
||||
\paragraph*{The code} You can see all the Cryptol code for our Enigma
|
||||
simulator in Appendix~\ref{app:enigma}.
|
||||
|
||||
\commentout{
|
||||
\begin{code}
|
||||
invSubst : (Permutation, Char) -> Char
|
||||
invSubst (key, c) = candidates ! 0
|
||||
where candidates = [0] # [ if c == k then a else p
|
||||
| k <- key
|
||||
| a <- ['A' .. 'Z']
|
||||
| p <- candidates
|
||||
]
|
||||
elem : {a, b} (fin 0, fin a, Cmp b) => (b, [a]b) -> Bit
|
||||
elem (x, xs) = matches ! 0
|
||||
where matches = [False] # [ m || (x == e) | e <- xs
|
||||
| m <- matches
|
||||
]
|
||||
sanityCheck = enigma (modelEnigma, "ENIGMAWASAREALLYCOOLMACHINE") == "UPEKTBSDROBVTUJGNCEHHGBXGTF"
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
19
docs/ProgrammingCryptol/enigma/EnigmaCode.tex
Normal file
19
docs/ProgrammingCryptol/enigma/EnigmaCode.tex
Normal file
@ -0,0 +1,19 @@
|
||||
\chapter{Enigma simulator}\label{app:enigma}
|
||||
In this appendix we present the Cryptol code for the enigma\indEnigma machine in its entirety for
|
||||
reference purposes. Chapter~\ref{chapter:enigma} has a detailed discussion on how the enigma machine worked, and the
|
||||
construction of the Cryptol model below.
|
||||
|
||||
\fvset{fontsize=\footnotesize}
|
||||
\VerbatimInput[numbers=left]{enigma/Enigma.cry}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
EnigmaEncapsulated = {
|
||||
include "Enigma.cry";
|
||||
};
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
13
docs/ProgrammingCryptol/enigma/Finite.cry
Normal file
13
docs/ProgrammingCryptol/enigma/Finite.cry
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014 Galois, Inc.
|
||||
* Distributed under the terms of the BSD3 license (see LICENSE file)
|
||||
*/
|
||||
|
||||
xs = [ 1 .. 100 ]
|
||||
|
||||
sumInf xs = iterSums
|
||||
where
|
||||
sums = [ 0 ] # [ x + y | x <- xs
|
||||
| y <- sums ]
|
||||
iterSums = [ x + y | x <- sums
|
||||
| y <- [ 1 ...] ]
|
2
docs/ProgrammingCryptol/enigma/Makefile
Normal file
2
docs/ProgrammingCryptol/enigma/Makefile
Normal file
@ -0,0 +1,2 @@
|
||||
test:
|
||||
cryptol-2 -b sanity.icry
|
42
docs/ProgrammingCryptol/enigma/Simple.cry
Normal file
42
docs/ProgrammingCryptol/enigma/Simple.cry
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014 Galois, Inc.
|
||||
* Distributed under the terms of the BSD3 license (see LICENSE file)
|
||||
*/
|
||||
|
||||
type Char = [8]
|
||||
type Permutation = String 26
|
||||
|
||||
invSubst : (Permutation, Char) -> Char
|
||||
invSubst (key, c) = candidates ! 0
|
||||
where candidates = [0] # [ if c == k then a else p
|
||||
| k <- key
|
||||
| a <- ['A' .. 'Z']
|
||||
| p <- candidates
|
||||
]
|
||||
|
||||
myrev : {n,a} (fin n) => [n+1][a] -> [n+1][a]
|
||||
myrev xs = [ xs!i | i <- [ 0 .. n] ]
|
||||
|
||||
sumAll xs = ys ! 0
|
||||
where ys = [0] # [x+y | x <- xs | y <- ys]
|
||||
|
||||
/*
|
||||
simpleRec : {n,a} (fin n) => [n]a -> a
|
||||
simpleRec xs = ret
|
||||
where
|
||||
(_,ret) = iters ! 0
|
||||
iters = [ (1,xs@0) ] #
|
||||
[ (i,x) | x <- xs
|
||||
| (i, _) <- iters ]
|
||||
|
||||
joinRotors : {n} (fin n) => [n]() -> [n]()
|
||||
joinRotors rotors = rotors'
|
||||
where
|
||||
ncrs = [(True, ())]
|
||||
# [ (notch, r)
|
||||
| r <- rotors
|
||||
| (notch, _) <- ncrs
|
||||
]
|
||||
rotors' = tail [ r | (_, r) <- ncrs ]
|
||||
|
||||
*/
|
3
docs/ProgrammingCryptol/enigma/sanity.icry
Normal file
3
docs/ProgrammingCryptol/enigma/sanity.icry
Normal file
@ -0,0 +1,3 @@
|
||||
:set warnDefaulting=off
|
||||
:l Enigma.tex
|
||||
sanityCheck
|
16
docs/ProgrammingCryptol/enigma/ticket141.cry
Normal file
16
docs/ProgrammingCryptol/enigma/ticket141.cry
Normal file
@ -0,0 +1,16 @@
|
||||
/*
|
||||
* Copyright (c) 2013-2014 Galois, Inc.
|
||||
* Distributed under the terms of the BSD3 license (see LICENSE file)
|
||||
*/
|
||||
|
||||
type Char = [8]
|
||||
type Permutation = String 26
|
||||
|
||||
invSubst : (String 26, Char) -> Char
|
||||
invSubst (key, c) = candidates ! 0
|
||||
where candidates = [0] # [ if c == k then a else p
|
||||
| k <- key
|
||||
| a <- ['A' .. 'Z']
|
||||
| p <- candidates
|
||||
]
|
||||
|
1
docs/ProgrammingCryptol/highAssurance/.gitignore
vendored
Normal file
1
docs/ProgrammingCryptol/highAssurance/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/auto
|
1125
docs/ProgrammingCryptol/highAssurance/HighAssurance.tex
Normal file
1125
docs/ProgrammingCryptol/highAssurance/HighAssurance.tex
Normal file
File diff suppressed because it is too large
Load Diff
8
docs/ProgrammingCryptol/highAssurance/Makefile
Normal file
8
docs/ProgrammingCryptol/highAssurance/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
Classic.cry:
|
||||
ln -s ../classic/Classic.cry .
|
||||
|
||||
Enigma.cry:
|
||||
ln -s ../enigma/Enigma.cry .
|
||||
|
||||
test: Enigma.cry Classic.cry
|
||||
cryptol-2 -b sanity.icry
|
4
docs/ProgrammingCryptol/highAssurance/sanity.icry
Normal file
4
docs/ProgrammingCryptol/highAssurance/sanity.icry
Normal file
@ -0,0 +1,4 @@
|
||||
:set warnDefaulting=off
|
||||
:set prover=yices
|
||||
:l HighAssurance.tex
|
||||
:prove caesarCorrect : ([8], String(8)) -> Bit
|
360
docs/ProgrammingCryptol/installation/Install.tex
Normal file
360
docs/ProgrammingCryptol/installation/Install.tex
Normal file
@ -0,0 +1,360 @@
|
||||
\commentout{
|
||||
\begin{code}
|
||||
module Installation where
|
||||
\end{code}
|
||||
}
|
||||
|
||||
\chapter{Installation and Tool Use}
|
||||
\label{cha:inst-tool-use}
|
||||
|
||||
The best way to learn Cryptol is to: (a)~read this book and related
|
||||
course notes and, more importantly, (b)~attempt the dozens of problems
|
||||
included herein. The only way to really learn a new language is to
|
||||
use it, so installing and using the Cryptol tool is critical to your
|
||||
success in using Cryptol.
|
||||
|
||||
%=====================================================================
|
||||
\section{Getting started}
|
||||
\label{sec:gettingstarted}
|
||||
\sectionWithAnswers{Getting started}{sec:gettingstarted}
|
||||
|
||||
How you download Cryptol and install it on your system is platform
|
||||
specific~\cite{CryptolWWW}. Once installed, we use Cryptol from
|
||||
inside a terminal window, by interacting with its read-eval-print
|
||||
loop. On a Linux/Mac machine, this simply amounts to typing:
|
||||
\begin{Verbatim}
|
||||
$ cryptol
|
||||
_ _
|
||||
___ _ __ _ _ _ __ | |_ ___ | |
|
||||
/ __| '__| | | | '_ \| __/ _ \| |
|
||||
| (__| | | |_| | |_) | || (_) | |
|
||||
\___|_| \__, | .__/ \__\___/|_|
|
||||
|___/|_| version 2.0.200
|
||||
|
||||
Loading module Cryptol
|
||||
Cryptol>
|
||||
\end{Verbatim}
|
||||
|
||||
\noindent Of course, your version number may be different, but for
|
||||
this document we will assume you are running at least version
|
||||
2.0\footnote{Version 2.0 of cryptol is a significant change from
|
||||
version 1. If you are already familiar with Cryptol version 1, there
|
||||
is a document in the Cryptol release that summarizes the changes.}.
|
||||
|
||||
On Windows, you typically click on the desktop icon to run Cryptol in
|
||||
a command window. Otherwise, the interaction mode is exactly the
|
||||
same, regardless of which platform you use to run Cryptol.
|
||||
|
||||
Once you have the {\tt Cryptol>} prompt displayed, you are good to go.
|
||||
You can directly type expressions (not declarations) and have Cryptol
|
||||
evaluate them for you. The extension for Cryptol program files is
|
||||
{\tt .cry}. If you place your program in a file called {\tt
|
||||
prog.cry}, then you can load it into Cryptol like this:
|
||||
\begin{Verbatim}
|
||||
Cryptol> :l prog.cry
|
||||
\end{Verbatim}
|
||||
\noindent or, by calling Cryptol from your shell as follows:
|
||||
\begin{Verbatim}
|
||||
$ cryptol prog.cry
|
||||
\end{Verbatim}
|
||||
|
||||
\begin{Exercise}\label{ex:helloWorld1}
|
||||
Obtain and install Cryptol on your machine. Start it up and type:
|
||||
\begin{Verbatim}
|
||||
Cryptol> "Hello World!"
|
||||
\end{Verbatim}
|
||||
What do you see printed?
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:helloWorld1}
|
||||
Here is the response I get:
|
||||
\begin{small}
|
||||
\begin{Verbatim}
|
||||
Cryptol> "Hello World!"
|
||||
[0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x21]
|
||||
\end{Verbatim}
|
||||
\end{small}
|
||||
As we shall see in Section~\ref{sec:charstring}, strings are just
|
||||
sequences of ASCII characters, so Cryptol is telling you the ASCII
|
||||
numbers corresponding to the letters.
|
||||
\end{Answer}
|
||||
\begin{Exercise}\label{ex:helloWorld2}
|
||||
Try the above exercise, after first issuing the following command:
|
||||
\begin{Verbatim}
|
||||
Cryptol> :set ascii=on
|
||||
\end{Verbatim}
|
||||
Why do you think this is not the default behavior?\indSettingASCII
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:helloWorld2}
|
||||
In this case we see:\indSettingASCII
|
||||
\begin{Verbatim}
|
||||
Cryptol> :set ascii=on
|
||||
Cryptol> "Hello World!"
|
||||
"Hello World!"
|
||||
\end{Verbatim}
|
||||
The command {\tt :set ascii=on} asks Cryptol to treat sequences of 8
|
||||
bit values as strings, which is how strings are really represented in
|
||||
Cryptol. This is not the default behavior, however, since sequences
|
||||
of 8 bit values can represent other things, especially in the domain
|
||||
of cryptography. The first behavior is typically what a
|
||||
crypto-programmer wants to see, and hence is the default.
|
||||
\end{Answer}
|
||||
|
||||
%=====================================================================
|
||||
\section{Technicalities}
|
||||
\label{sec:technicalities}
|
||||
|
||||
Before we dive into various aspects of Cryptol, it is good to get some
|
||||
of the technicalities out of the way. Feel free to skim through these
|
||||
items for future reference. The summary below describes language
|
||||
features, as well as commands that are available at the {\tt Cryptol>}
|
||||
prompt. Commands all begin with the {\tt :} character.
|
||||
|
||||
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
\subsection{Language features}
|
||||
\label{sec:language-features}
|
||||
|
||||
The Cryptol language is a size-polymorphic dependently-typed
|
||||
programming language with support for polymorphic recursive functions.
|
||||
It has a small syntax tuned for applied cryptography, a lightweight
|
||||
module system, a pseudo-Real/Eval/Print/Loop (REPL) top-level, and a
|
||||
rich set of built-in tools for performing high-assurance (literate)
|
||||
programming. Cryptol performs fairly advanced type inference, though
|
||||
as with most mainstream strongly typed functional languages, types can
|
||||
be manually specified as well. What follows is a brief tour of
|
||||
Cryptol's most salient language features.
|
||||
|
||||
\paragraph*{Case sensitivity}
|
||||
Cryptol identifiers are case sensitive. {\tt A} and {\tt a} are two
|
||||
different things.\indCaseSensitive
|
||||
|
||||
\paragraph*{Indentation and whitespace}
|
||||
Cryptol uses indentation-level (instead of \{\}'s) to denote blocks.
|
||||
Whitespace within a line is immaterial, as is the specific amount of
|
||||
indentation. However, consistent indentation will save you tons of
|
||||
trouble down the road! Do not mix tabs and spaces for your
|
||||
indentation. Spaces are generally preferred.
|
||||
|
||||
\paragraph*{Escape characters}
|
||||
Long lines can be continued with the end-of-line escape character
|
||||
\texttt{$\backslash$}, as in many programming languages.\indLineCont
|
||||
There are no built-in character escape characters, as Cryptol performs
|
||||
no interpretation on bytes beyond printing byte streams out in ASCII,
|
||||
as discussed above.
|
||||
|
||||
\paragraph*{Comments}\indComments
|
||||
Block comments are enclosed in {\tt /*} and {\tt */}, and they can be
|
||||
nested. Line comments start with {\tt //} and run to the end of the
|
||||
line.
|
||||
|
||||
\paragraph*{Order of definitions}
|
||||
The order of definitions is immaterial. You can write your definitions
|
||||
in any order, and earlier entries can refer to latter ones.
|
||||
|
||||
\paragraph*{Typing}
|
||||
Cryptol is strongly typed. This means that the interpreter will catch
|
||||
most common mistakes in programming during the type-checking phase,
|
||||
before runtime.
|
||||
|
||||
\paragraph*{Type inference}
|
||||
Cryptol has type inference. This means that the user can omit type
|
||||
signatures because the inference engine will supply
|
||||
them.\indTypeInference
|
||||
|
||||
\paragraph*{Type signatures}
|
||||
While writing type signatures are optional, writing them down is
|
||||
considered good practice.\indSignature
|
||||
|
||||
\paragraph*{Polymorphism}
|
||||
Cryptol functions can be polymorphic, which means they can operate on
|
||||
many different types. Beware that the type which Cryptol infers might
|
||||
be too polymorphic, so it is good practice to write your signatures,
|
||||
or at least check what Cryptol inferred is what you had in
|
||||
mind.\indPolymorphism\indSignature
|
||||
|
||||
\paragraph*{Module system}
|
||||
Each Cryptol file defines a {\it module}. Modules allow Cryptol
|
||||
developers to manage which definitions are exported (the default
|
||||
behavior) and which definitions are internal-only ({\it private}). At
|
||||
the beginning of each Cryptol file, you specify its name and use {\tt
|
||||
import}\indImport to specify the modules on which it
|
||||
relies.\indModuleSystem Definitions are {\tt public} by default, but
|
||||
you can hide them from modules that import your code via the {\tt
|
||||
private} keyword at the start of each private definition,\indPrivate
|
||||
like this:
|
||||
\begin{Verbatim}
|
||||
module test where
|
||||
private
|
||||
hiddenConst = 0x5 // hidden from importing modules
|
||||
// end of indented block indicates symbols are available to importing modules
|
||||
revealedConst = 0x15
|
||||
\end{Verbatim}
|
||||
Note that the filename should correspond to the module name, so {\tt
|
||||
module test} must be defined in a file called {\tt test.cry}.
|
||||
|
||||
\todo[inline]{Say what happens if you try to put multiple modules into a
|
||||
single file.}
|
||||
|
||||
\todo[inline]{Check with Trevor about module hierarchy and module visibility;
|
||||
lambda or default modules; what modules are visible in the top level
|
||||
- talk about Cryptol prelude here?}
|
||||
|
||||
\paragraph*{Literate programming}
|
||||
You can feed \LaTeX~files to Cryptol (i.e., files with extension {\tt
|
||||
.tex}). Cryptol will look for \verb|\begin{code}| and
|
||||
\verb|\end{code}| marks to extract Cryptol code. Everything else
|
||||
will be comments as far as Cryptol is concerned. In fact, the book
|
||||
you are reading is a Literate Cryptol program.\indLiterateProgramming
|
||||
|
||||
\todo[inline]{Discuss Cryptol support for literate Markdown. Use ticks to
|
||||
delimit code blocks in Markdown layout. Talk with Trevor.}
|
||||
|
||||
\paragraph*{Completion}
|
||||
On UNIX-based machines, you can press tab at any time and Cryptol will
|
||||
suggests completions based on the context. You can retrieve your
|
||||
prior commands using the usual means (arrow keys or Emacs
|
||||
keybindings).\indCompletion
|
||||
|
||||
\todo[inline]{Ask Adam F about the best way to describe what can be tab-completed.}
|
||||
\todo[inline]{Is readline on windows still broken / worse than Unix?}
|
||||
|
||||
%~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
\subsection{Commands}
|
||||
\label{sec:commands}
|
||||
|
||||
\paragraph*{Querying types}
|
||||
You can ask Cryptol to tell you the type of an expression by typing
|
||||
{\tt :type <expr>} (or {\tt :t} for short). If {\tt foo} is the name
|
||||
of a definition (function or otherwise), you can ask its type by
|
||||
issuing {\tt :type foo}.\indCmdType It is common practice to define a
|
||||
function, ask Cryptol its type, and copy the response back to your
|
||||
source code. While this is somewhat contrived, it is usually better
|
||||
than not writing signatures at all.\indSignature In order to query the
|
||||
type of an infix operator (e.g., {\tt +}, {\tt ==}, etc.) you will need
|
||||
to surround the operator with {\tt ()}'s, like this:
|
||||
\begin{Verbatim}
|
||||
Cryptol> :t (+)
|
||||
+ : {a} (Arith a) => a -> a -> a
|
||||
\end{Verbatim}
|
||||
|
||||
\paragraph*{Browsing definitions}
|
||||
The command {\tt :browse} (or {\tt :b} for short) will display all the
|
||||
names you have defined, along with their types.\indCmdBrowse
|
||||
|
||||
\paragraph*{Getting help}
|
||||
The command {\tt :help} will show you all the available
|
||||
commands.\indCmdHelp Other useful implicit help invocations are:
|
||||
(a)~to type tab at the {\tt Cryptol>} prompt, which will list all of
|
||||
the operators available in Cryptol code, (b)~typing {\tt :set} with no
|
||||
argument, which shows you the parameters that can be set, and (c), as
|
||||
noted elsewhere, {\tt :browse} to see the names of functions and type
|
||||
aliases you have defined, along with their types.
|
||||
|
||||
\todo[inline]{What should \texttt{:help symbolname} do, especially for
|
||||
prelude functions and types? How about for commands?}
|
||||
|
||||
\begin{center}
|
||||
\begin{tabular*}{0.75\textwidth}[h]{c|c|l}
|
||||
\hline
|
||||
| \textbf{Option} | \textbf{Default value} | \textbf{Meaning} | \\
|
||||
\hline
|
||||
| \texttt{ascii} | \texttt{off} | \quad | \\
|
||||
| \texttt{base} | \texttt{} | \quad | \\
|
||||
| \texttt{debug} | \texttt{} | \quad | \\
|
||||
| \texttt{infLength} | \texttt{} | \quad | \\
|
||||
| \texttt{iteSolver} | \texttt{} | \todo[inline]{Talk to Brian.} | \\
|
||||
| \texttt{prover} | \texttt{} | \quad | \\
|
||||
| \texttt{tests} | \texttt{} | \quad | \\
|
||||
| \texttt{warnDefaulting} | \texttt{} | \quad | \\
|
||||
\hline
|
||||
\label{tab:set_options}
|
||||
\end{tabular*}
|
||||
\end{center}
|
||||
\paragraph*{Environment options}
|
||||
A variety of environment options are set through the use of the
|
||||
\texttt{:set} command. These options may change over time and some
|
||||
options may be available only on specific platforms. The current
|
||||
options are summarized in~\autoref{tab:set_options}.
|
||||
|
||||
\todo[inline]{Ensure index references exist for all commands.}
|
||||
|
||||
\paragraph*{Quitting}
|
||||
You can quit Cryptol by using the command {\tt :quit} (aka
|
||||
\texttt{:q}). On Mac/Linux you can press Ctrl-D, and on Windows use
|
||||
Ctrl-Z, for the same effect.\indCmdQuit
|
||||
|
||||
\paragraph*{Loading and reloading files}
|
||||
You load your program in Cryptol using {\tt :load <filename>} (or
|
||||
\texttt{:l} for short). However, it is customary to use the extension
|
||||
{\tt .cry} for Cryptol programs.\indCmdLoad If you edit the source
|
||||
file loaded into Cryptol from a separate context, you can reload it
|
||||
into Cryptol using the command {\tt :reload} (abbreviated {\tt
|
||||
:r}).\indCmdReload
|
||||
|
||||
\paragraph*{Invoking your editor}
|
||||
You can invoke your editor using the command {\tt :edit} (abbreviated
|
||||
\texttt{:e}).\indCmdEdit The default editor invoked is
|
||||
\texttt{vi}. You override the default using the standard
|
||||
\texttt{EDITOR} environmental variable in your shell.\indSettingEditor
|
||||
|
||||
\todo[inline]{I have filed a feature enhancement for missing \texttt{editor}
|
||||
environment variable as
|
||||
\href{https://www.galois.com/cryptol/ticket/273}{ticket \#273}.
|
||||
We want to write: ``You set your favorite editor by :set
|
||||
editor=/path/to/editor.''}
|
||||
|
||||
\paragraph*{Running shell commands}
|
||||
You can run Unix shell commands from within Cryptol like this: {\tt :!
|
||||
cat test.cry}.\indCmdShell
|
||||
|
||||
\paragraph*{Changing working directory}
|
||||
You can change the current working directory of Cryptol like this:
|
||||
\texttt{:cd some/path}. Note that the path syntax is
|
||||
platform-dependent.
|
||||
% indeed it is, but both \'s and /'s are supported on windows.
|
||||
% currently directories with spaces break things...issue 291 has been filed
|
||||
% dylan - 2014-03-27
|
||||
|
||||
\paragraph*{Loading a module}
|
||||
At the Cryptol prompt you can load a module by name with the {\tt
|
||||
:module} command.\indCmdLoadModule
|
||||
|
||||
The next three commands all operate on \emph{properties}. All take
|
||||
either one or zero arguments. If one argument is provided, then that
|
||||
property is the focus of the command; otherwise all properties in the
|
||||
current context are checked. All three commands are covered in detail
|
||||
in~\autoref{cha:high-assur-progr}.
|
||||
|
||||
\paragraph*{Checking a property through random testing}
|
||||
The \texttt{:check} command performs random value testing on a
|
||||
property to increase one's confidence that the property is valid.
|
||||
See~\autoref{sec:quickcheck} for more detailed information.
|
||||
|
||||
\paragraph*{Verifying a property through automated theorem proving}
|
||||
The \texttt{:prove} command uses an external SMT solver to attempt to
|
||||
automatically formally prove that a given property is valid.
|
||||
See~\autoref{sec:formal-proofs} for more detailed information.
|
||||
|
||||
\paragraph*{Finding a satisfying assignment for a property}
|
||||
The \texttt{:sat} command uses an external SAT solver to attempt to
|
||||
find a satisfying assignment to a property. See~\autoref{sec:sat} for
|
||||
more detailed information.
|
||||
|
||||
\paragraph*{Type specialization}
|
||||
Discuss \texttt{:debug\_specialize}. \todo[inline]{Dylan?}
|
||||
|
||||
\vspace{2cm}
|
||||
|
||||
The next chapter provides a ``crash course'' introduction to the
|
||||
Cryptol programming language.
|
||||
|
||||
%=====================================================================
|
||||
%\section{Using Cryptol: The Big Picture}
|
||||
%\label{sec:using-cryptol}
|
||||
|
||||
\todo[inline]{2.1: Add some big picture on process and use of the tools.
|
||||
Put it on the website now and then migrate it to the book later.}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
5
docs/ProgrammingCryptol/main/.gitignore
vendored
Normal file
5
docs/ProgrammingCryptol/main/.gitignore
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
/Cryptol.glo
|
||||
/Cryptol.ist
|
||||
/Cryptol.pdf
|
||||
/Cryptol.tdo
|
||||
/auto
|
307
docs/ProgrammingCryptol/main/Cryptol-fullpage.tex
Normal file
307
docs/ProgrammingCryptol/main/Cryptol-fullpage.tex
Normal file
@ -0,0 +1,307 @@
|
||||
\documentclass[twoside]{book}
|
||||
% \usepackage{layout}
|
||||
\usepackage{amsfonts}
|
||||
\usepackage{xspace}
|
||||
\usepackage{url}
|
||||
\usepackage{subfigure}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{lastpage}
|
||||
\usepackage{makeidx}
|
||||
\usepackage[myheadings]{fullpage}
|
||||
\usepackage{verbatim}
|
||||
\usepackage{fancyvrb}
|
||||
\usepackage{amsmath, amsthm, amssymb}
|
||||
\usepackage{fancyhdr}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{pdfpages}
|
||||
\usepackage[answerdelayed,lastexercise]{utils/exercise}
|
||||
\usepackage[xetex,bookmarks=true,pagebackref=true,linktocpage=true]{hyperref}
|
||||
\usepackage[style=list]{utils/glossary}
|
||||
\usepackage{adjustbox}
|
||||
|
||||
\usepackage[paperwidth=5.5in,paperheight=8.5in]{geometry}
|
||||
|
||||
\setlength{\textwidth}{350pt}
|
||||
\setlength{\textheight}{502pt}
|
||||
\advance\voffset by -72pt
|
||||
\setlength{\hoffset}{-36pt}
|
||||
% \setlength{\oddsidemargin}{36pt}
|
||||
% \setlength{\evensidemargin}{-36pt}
|
||||
|
||||
\newcommand{\titleline}{Programming in Cryptol}
|
||||
|
||||
\hypersetup{%
|
||||
pdftitle = \titleline,
|
||||
pdfkeywords = {Cryptol, Cryptography, Programming},
|
||||
pdfauthor = {Levent Erk\"{o}k},
|
||||
pdfpagemode = UseOutlines
|
||||
}
|
||||
|
||||
\input{utils/Indexes.tex}
|
||||
\input{utils/GlossaryItems.tex}
|
||||
\input{utils/trickery.tex}
|
||||
|
||||
% fonts
|
||||
\usepackage{fontspec}
|
||||
\usepackage{xunicode}
|
||||
\usepackage{xltxtra}
|
||||
\defaultfontfeatures{Mapping=tex-text}
|
||||
\setmainfont[]{Times}
|
||||
\setsansfont[]{Helvetica}
|
||||
%% \setmonofont[Scale=0.85]{Courier}
|
||||
\usepackage{sectsty}
|
||||
\allsectionsfont{\sffamily}
|
||||
|
||||
\newcommand{\todo}[1]{\begin{center}\framebox{\begin{minipage}{0.8\textwidth}{{\bf TODO:} #1}\end{minipage}}\end{center}}
|
||||
\newcommand{\lamex}{\ensuremath{\lambda}-expression\indLamExp}
|
||||
\newcommand{\lamexs}{\ensuremath{\lambda}-expressions\indLamExp}
|
||||
\makeatletter
|
||||
\def\imod#1{\allowbreak\mkern10mu({\operator@font mod}\,\,#1)}
|
||||
\makeatother
|
||||
\newcommand{\advanced}{\begin{center}\framebox{\begin{minipage}{0.95\textwidth}{{\bf Note:} The material in this section
|
||||
is aimed for the more advanced reader. It can be skipped on a first reading without loss of continuity.}\end{minipage}}\end{center}}
|
||||
|
||||
\newcommand{\sectionWithAnswers}[2]{%
|
||||
\section{#1}\label{#2}%
|
||||
\AnswerBoxSectionMark{Section \arabic{chapter}.\arabic{section} #1 (p.\pageref{#2})}%
|
||||
\AnswerBoxExecute{\addcontentsline{toc}{section}{\texorpdfstring{\parbox{2.3em}{\arabic{chapter}.\arabic{section}\ }}{(\arabic{chapter}.\arabic{section})\ }#1}}%
|
||||
}
|
||||
|
||||
\theoremstyle{definition}
|
||||
\newcommand{\commentout}[1]{}
|
||||
\DefineVerbatimEnvironment{code}{Verbatim}{}
|
||||
\renewcommand{\ExerciseHeaderTitle}{\ExerciseTitle}
|
||||
\renewcommand{\ExerciseHeader}{\textbf{\hspace*{-\parindent}\ExerciseName\ \theExercise.\ }}
|
||||
\renewcommand{\AnswerHeader}{\textbf{\hspace*{-\parindent}\ExerciseName\ \theExercise.\ }}
|
||||
\renewcounter{Exercise}[section]
|
||||
\newcommand{\unparagraph}{\paragraph{$\,\,\,$\hspace*{-\parindent}}}
|
||||
|
||||
% various little text sections:
|
||||
\newtheorem*{tip}{Tip}
|
||||
\newtheorem*{hint}{Hint}
|
||||
\newtheorem*{nb}{NB}
|
||||
\newtheorem*{notesThm}{Note}
|
||||
\newcommand{\note}[1]{\begin{notesThm}{#1}\end{notesThm}}
|
||||
\newcommand{\lhint}[1]{({\bf Hint.}\ #1)}
|
||||
\newcommand{\ansref}[1]{{\bf (p.~\pageref{#1})}}
|
||||
%% \newcommand{\draftdate}{DRAFT of \today}
|
||||
\setlength{\voffset}{-1cm}
|
||||
\setlength{\headsep}{2cm}
|
||||
\setlength{\headheight}{15.2pt}
|
||||
\renewcommand{\headrulewidth}{0pt} % no line on top
|
||||
\renewcommand{\footrulewidth}{.5pt} % line on bottom
|
||||
\renewcommand{\chaptermark}[1]{\markboth{#1}{}}
|
||||
\renewcommand{\sectionmark}[1]{\markright{#1}{}}
|
||||
\cfoot{}
|
||||
\fancyfoot[LE,RO]{\fancyplain{}{\textsf{\thepage}}}
|
||||
\fancyfoot[LO,RE]{\fancyplain{}{\textsf{\copyright\ 2010--2013, Galois, Inc.}}}
|
||||
%% \fancyhead[LE]{\fancyplain{}{\textsf{\draftdate}}}
|
||||
%% \fancyhead[RO]{\fancyplain{}{\textsf{DO NOT DISTRIBUTE!}}}
|
||||
\fancyhead[RO,LE]{\fancyplain{}{}} %% outer
|
||||
%\fancyhead[LO,RE]{\fancyplain{}{\textsf{\nouppercase{\rightmark}}}}
|
||||
\fancyhead[LO,RE]{\fancyplain{}{\textsf{\nouppercase{\rightmark}}}} %% inner
|
||||
\pagestyle{fancyplain}
|
||||
|
||||
\makeglossary
|
||||
\makeindex
|
||||
|
||||
\begin{document}
|
||||
|
||||
\title{\Huge{\bf \titleline}}
|
||||
\author{\\$ $\\$ $\\
|
||||
Levent Erk\"{o}k\\
|
||||
%\url{levent.erkok@galois.com}
|
||||
\\$ $\\
|
||||
Galois, Inc.\\
|
||||
421 SW 6th Ave., Suite 300\\Portland, OR 97204}
|
||||
\date{
|
||||
\vspace*{2cm}$ $\\
|
||||
\includegraphics{utils/galois.jpg}
|
||||
}
|
||||
|
||||
\pagenumbering{roman}
|
||||
|
||||
\includepdf[pages={1},scale=0.8]{cover/Cover.pdf}
|
||||
|
||||
|
||||
% \maketitle
|
||||
%%
|
||||
\index{inference|see{type, inference}}
|
||||
\index{signature|see{type, signature}}
|
||||
\index{polymorphism|see{type, polymorphism}}
|
||||
\index{monomorphism|see{type, monomorphism}}
|
||||
\index{overloading|see{type, overloading}}
|
||||
\index{undecidable|see{type, undecidable}}
|
||||
\index{predicates|see{type, predicates}}
|
||||
\index{defaulting|see{type, defaulting}}
|
||||
\index{fin@\texttt{fin}|see{type, fin}}
|
||||
\index{ambiguous constraints|see{type, ambiguous}}
|
||||
\index{wildcard|see{\texttt{\_} (underscore)}}
|
||||
\index{lambda expression|see{\ensuremath{\lambda}-expression}}
|
||||
\index{pdiv@\texttt{pdiv}|see{polynomial, division}}
|
||||
\index{pmod@\texttt{pmod}|see{polynomial, modulus}}
|
||||
\index{pmult@\texttt{pmult}|see{polynomial, multiplication}}
|
||||
\index{000GF28@GF($2^8$)|see{galois field}}
|
||||
|
||||
\setlength{\headsep}{24pt}
|
||||
% \layout
|
||||
|
||||
%%%%%% PREFACE
|
||||
%\input{preface/Preface.tex}
|
||||
\input{preface/Notice.tex}
|
||||
|
||||
%%%%%% TOC
|
||||
\tableofcontents
|
||||
|
||||
\includepdf[pages={1}]{cover/Blank.pdf}
|
||||
\newpage
|
||||
|
||||
\setcounter{page}{1}
|
||||
\pagenumbering{arabic}
|
||||
%%%%%% Crash Course
|
||||
\input{crashCourse/CrashCourse.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../crashCourse/CrashCourse.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%%%% Transposition ciphers
|
||||
\input{classic/Classic.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../classic/Classic.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%%%% Enigma
|
||||
\input{enigma/Enigma.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../enigma/Enigma.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%%%% High assurance
|
||||
%% TODO - after ticket 96
|
||||
%% \input{highAssurance/HighAssurance.tex}
|
||||
%% \commentout{
|
||||
%% \begin{code}
|
||||
%% include "../highAssurance/HighAssurance.tex";
|
||||
%% \end{code}
|
||||
%% }
|
||||
|
||||
%%%%%% DES
|
||||
% \chapter{DES: The Data Encryption Standard}
|
||||
|
||||
%%%%%% AES
|
||||
\input{aes/AES.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../aes/AES.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%%%% SHA
|
||||
% \chapter{SHA: The Secure Hash Algorithm}
|
||||
|
||||
%\chapter{Advanced proof techniques}
|
||||
%\section{Assumed equality}
|
||||
%\section{Uninterpreted functions}
|
||||
%\section{Proving AES correct}\label{sec:proveaes}
|
||||
%In Section~\ref{sec:aescorrectattempt}, we wrote down the below Cryptol theorem stating that our AES\indAES encryption/decryption functions work correctly:
|
||||
%\begin{Verbatim}
|
||||
% theorem AESCorrect: {msg key}. aesDecrypt (aesEncrypt (msg, key), key) == msg;
|
||||
%\end{Verbatim}
|
||||
|
||||
% However, we were not able to do an automated proof of this fact, as it is beyond the scope of what SAT-based equivalence checkers can handle. In this
|
||||
% section we will use our new tools to attack this problem and actually complete the proof in a reasonable amount of time.
|
||||
|
||||
%%%%%% SAT solving
|
||||
% \chapter{Using satisfiability solvers: Solving Sudoku and N-Queens in Cryptol}\label{chap:usingsat}
|
||||
|
||||
%%%%%% Hardware
|
||||
% \chapter{Generating and proving hardware correct}
|
||||
|
||||
%%%%%% Pitfalls
|
||||
% \chapter{Pitfalls}
|
||||
% \section{Defaulting}\label{sec:pitfall:defaulting}
|
||||
% \todo{Talk about defaulting gotchas}
|
||||
% \section{Evaluation order}\label{sec:pitfall:evorder}
|
||||
% \todo{Talk about there's no short-circuit except for if-then-else, although models might differ.}
|
||||
% \section{Theorems and safety checking}\label{sec:pitfall:thmexceptions}
|
||||
% \todo{Talk about safety failures and theorems}
|
||||
% \todo{Talk about why {\tt implies (x, y) = if x then y else False} is not a substitute for {\tt if-then-else}}
|
||||
% \todo{Talk about assumeSafe}
|
||||
|
||||
%%%%%% Toolbox
|
||||
% \chapter{Programmer's toolbox}
|
||||
% \section{Pretty printing using {\tt format}}
|
||||
% \section{Debugging code using {\tt trace}}
|
||||
|
||||
%%%%%% Miscallaneous
|
||||
% \input{misc/Misc.tex}
|
||||
% \commentout{
|
||||
% \begin{code}
|
||||
% include "../misc/Misc.tex";
|
||||
% \end{code}
|
||||
% }
|
||||
|
||||
\appendix
|
||||
% \fancyhead[LO,RE]{\fancyplain{}{\textsf{\nouppercase{\leftmark}}}}
|
||||
\fancyhead[LO,RE]{\fancyplain{}{}}
|
||||
|
||||
%%%% Solutions
|
||||
\chapter{Solutions to selected exercises}
|
||||
As with any language, there are usually multiple ways to write the same
|
||||
function in Cryptol. We have tried to use the most idiomatic
|
||||
Cryptol code segments in our solutions. Note that Cryptol prints
|
||||
numbers out in hexadecimal by default. In most of the answers below, we
|
||||
have implicitly used the command {\tt :set base=10} to print numbers
|
||||
out in decimal for readability.\indSettingBase
|
||||
\shipoutAnswer
|
||||
|
||||
%%%% Cryptol primitives
|
||||
\input{prims/Primitives.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../prims/Primitives.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%% Enigma code
|
||||
\input{enigma/EnigmaCode.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../enigma/EnigmaCode.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%% AES code
|
||||
\input{aes/AESCode.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../aes/AESCode.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%% Glossary
|
||||
\printglossary
|
||||
\addcontentsline{toc}{chapter}{Glossary}
|
||||
|
||||
%%%% Bibliography
|
||||
\bibliography{bib/cryptol}
|
||||
\bibliographystyle{plain}
|
||||
|
||||
%%%% Index
|
||||
\printindex
|
||||
|
||||
%%%% sanity checks
|
||||
% \commentout{
|
||||
% \begin{code}
|
||||
% isEverythingSane = ~zero == checks
|
||||
% where checks = [aesEncSanityCheck aesDecSanityCheck];
|
||||
% \end{code}
|
||||
% }
|
||||
|
||||
\end{document}
|
377
docs/ProgrammingCryptol/main/Cryptol.tex
Normal file
377
docs/ProgrammingCryptol/main/Cryptol.tex
Normal file
@ -0,0 +1,377 @@
|
||||
%
|
||||
% Programming in Cryptol
|
||||
% Galois, Inc.
|
||||
% Levent Erkok, Dylan McNamee, Joseph Kiniry, and others
|
||||
%
|
||||
|
||||
\documentclass[twoside]{book}
|
||||
% \usepackage{layout}
|
||||
% \usepackage{diagrams}
|
||||
\usepackage{amsfonts}
|
||||
\usepackage{xspace}
|
||||
\usepackage{url}
|
||||
\usepackage{subfigure}
|
||||
\usepackage{graphicx}
|
||||
\usepackage{lastpage}
|
||||
\usepackage{makeidx}
|
||||
\usepackage[disable]{todonotes}
|
||||
\usepackage[myheadings]{fullpage}
|
||||
\usepackage{verbatim}
|
||||
%% \usepackage[lighttt]{lmodern}
|
||||
%% \usepackage[ttscale=1.15]{lmodern}
|
||||
\usepackage{fancyvrb}
|
||||
\usepackage{amsmath, amsthm, amssymb}
|
||||
\usepackage{fancyhdr}
|
||||
\usepackage{xcolor}
|
||||
\usepackage{pdfpages}
|
||||
\usepackage[answerdelayed,lastexercise]{utils/exercise}
|
||||
\usepackage[bookmarks=true,pagebackref=true,linktocpage=true]{hyperref}
|
||||
\usepackage[style=list]{utils/glossary}
|
||||
\usepackage{adjustbox}
|
||||
%\usepackage[paperwidth=5.5in,paperheight=8.5in]{geometry}
|
||||
\usepackage{geometry}
|
||||
|
||||
%\setlength{\textwidth}{340pt}
|
||||
%\setlength{\textheight}{502pt}
|
||||
|
||||
\newcommand{\titleline}{Programming in Cryptol}
|
||||
|
||||
\hypersetup{%
|
||||
pdftitle = \titleline,
|
||||
pdfkeywords = {Cryptol, Cryptography, Programming},
|
||||
pdfauthor = {Galois, Inc.},
|
||||
pdfpagemode = UseOutlines
|
||||
}
|
||||
|
||||
\input{utils/Indexes.tex}
|
||||
\input{utils/GlossaryItems.tex}
|
||||
\input{utils/trickery.tex}
|
||||
|
||||
% fonts
|
||||
\usepackage{fontspec}
|
||||
\usepackage{xunicode}
|
||||
\usepackage{xltxtra}
|
||||
\defaultfontfeatures{Mapping=tex-text}
|
||||
\setmainfont[]{Times}
|
||||
\setsansfont[]{Helvetica}
|
||||
\setmonofont[Scale=0.85]{Courier}
|
||||
\usepackage{sectsty}
|
||||
\allsectionsfont{\sffamily}
|
||||
|
||||
\newcommand{\lamex}{\ensuremath{\lambda}-expression\indLamExp}
|
||||
\newcommand{\lamexs}{\ensuremath{\lambda}-expressions\indLamExp}
|
||||
\makeatletter
|
||||
\def\imod#1{\allowbreak\mkern3mu({\operator@font mod}\,\,#1)}
|
||||
\makeatother
|
||||
|
||||
\newcommand{\ticket}[1]{\href{https://www.galois.com/cryptol/ticket/#1}{ticket \##1}}
|
||||
|
||||
\newcommand{\advanced}{\begin{center}\framebox{\begin{minipage}{0.95\textwidth}{{\bf
|
||||
Note:} The material in this section is aimed for the more
|
||||
advanced reader. It can be skipped on a first reading
|
||||
without loss of continuity.}\end{minipage}}\end{center}}
|
||||
|
||||
\newcommand{\sectionWithAnswers}[2]{%
|
||||
\AnswerBoxSectionMark{Section \arabic{chapter}.\arabic{section} #1 (p.\pageref{#2})}%
|
||||
\AnswerBoxExecute{\addcontentsline{toc}{section}{\texorpdfstring{\parbox{2.3em}{\arabic{chapter}.\arabic{section}\ }}{(\arabic{chapter}.\arabic{section})\ }#1}}%
|
||||
}
|
||||
|
||||
\theoremstyle{definition}
|
||||
\newcommand{\commentout}[1]{}
|
||||
\DefineVerbatimEnvironment{code}{Verbatim}{}
|
||||
\renewcommand{\ExerciseHeaderTitle}{\ExerciseTitle}
|
||||
\renewcommand{\ExerciseHeader}{\textbf{\hspace*{-\parindent}\ExerciseName\ \theExercise.\ }}
|
||||
\renewcommand{\AnswerHeader}{\textbf{\hspace*{-\parindent}\ExerciseName\ \theExercise.\ }}
|
||||
\renewcounter{Exercise}[chapter]
|
||||
\newcommand{\unparagraph}{\paragraph{$\,\,\,$\hspace*{-\parindent}}}
|
||||
|
||||
% various little text sections:
|
||||
\newtheorem*{tip}{Tip}
|
||||
\newtheorem*{hint}{Hint}
|
||||
\newtheorem*{nb}{NB}
|
||||
\newtheorem*{notesThm}{Note}
|
||||
\newcommand{\note}[1]{\begin{notesThm}{#1}\end{notesThm}}
|
||||
\newcommand{\lhint}[1]{({\bf Hint:}\ #1)}
|
||||
\newcommand{\ansref}[1]{{\bf (p.~\pageref{#1})}}
|
||||
%% \newcommand{\draftdate}{DRAFT of \today}
|
||||
\setlength{\headsep}{2cm}
|
||||
\setlength{\headheight}{15.2pt}
|
||||
\renewcommand{\headrulewidth}{0pt} % no line on top
|
||||
\renewcommand{\footrulewidth}{.5pt} % line on bottom
|
||||
\renewcommand{\chaptermark}[1]{\markboth{#1}{}}
|
||||
\renewcommand{\sectionmark}[1]{\markright{#1}{}}
|
||||
\newcommand{\changefont}{%
|
||||
\fontsize{9}{10}\selectfont
|
||||
}
|
||||
\cfoot{}
|
||||
\fancyfoot[LE,RO]{\changefont{\textsf{\thepage}}}
|
||||
\fancyfoot[LO,RE]{\changefont{\textsf{\copyright\ 2010--2014, Galois, Inc.}}}
|
||||
%% \fancyhead[LE]{\fancyplain{}{\textsf{\draftdate}}}
|
||||
%% \fancyhead[RO]{\fancyplain{}{\textsf{DO NOT DISTRIBUTE!}}}
|
||||
\fancyhead[RO,LE]{\fancyplain{}{}} %% outer
|
||||
%\fancyhead[LO,RE]{\fancyplain{}{\textsf{\nouppercase{\rightmark}}}}
|
||||
\fancyhead[LO,RE]{\fancyplain{}{\textsf{\nouppercase{\rightmark}}}} %% inner
|
||||
\pagestyle{fancyplain}
|
||||
|
||||
\makeglossary
|
||||
\makeindex
|
||||
|
||||
\begin{document}
|
||||
|
||||
\title{\Huge{\bf \titleline}}
|
||||
\author{\\$ $\\$ $\\
|
||||
Galois, Inc.\\
|
||||
421 SW 6th Ave., Suite 300\\Portland, OR 97204}
|
||||
\date{
|
||||
\vspace*{2cm}$ $\\
|
||||
\includegraphics{utils/galois.jpg}
|
||||
}
|
||||
|
||||
\pagenumbering{roman}
|
||||
|
||||
\includepdf[pages={1},scale=1.0]{cover/CryptolSmallCover.pdf}
|
||||
|
||||
\advance\voffset by -26pt
|
||||
\setlength{\hoffset}{-26pt}
|
||||
% \setlength{\oddsidemargin}{36pt}
|
||||
% \setlength{\evensidemargin}{-36pt}
|
||||
|
||||
% \maketitle
|
||||
%%
|
||||
\index{inference|see{type, inference}}
|
||||
\index{signature|see{type, signature}}
|
||||
\index{polymorphism|see{type, polymorphism}}
|
||||
\index{monomorphism|see{type, monomorphism}}
|
||||
\index{overloading|see{type, overloading}}
|
||||
\index{undecidable|see{type, undecidable}}
|
||||
\index{predicates|see{type, predicates}}
|
||||
\index{defaulting|see{type, defaulting}}
|
||||
\index{fin@\texttt{fin}|see{type, fin}}
|
||||
\index{ambiguous constraints|see{type, ambiguous}}
|
||||
\index{wildcard|see{\texttt{\_} (underscore)}}
|
||||
\index{lambda expression|see{\ensuremath{\lambda}-expression}}
|
||||
\index{pdiv@\texttt{pdiv}|see{polynomial, division}}
|
||||
\index{pmod@\texttt{pmod}|see{polynomial, modulus}}
|
||||
\index{pmult@\texttt{pmult}|see{polynomial, multiplication}}
|
||||
\index{000GF28@GF($2^8$)|see{galois field}}
|
||||
|
||||
\setlength{\headsep}{24pt}
|
||||
% \layout
|
||||
|
||||
\input{title/Title.tex}
|
||||
\newpage
|
||||
|
||||
\input{preface/Notice.tex}
|
||||
\newpage
|
||||
|
||||
%%%%%% TOC
|
||||
\tableofcontents
|
||||
|
||||
% \includepdf[pages={1}]{cover/Blank.pdf}
|
||||
\vfill
|
||||
\eject
|
||||
|
||||
\listoftodos
|
||||
\newpage
|
||||
|
||||
%%%%%% Preface
|
||||
\input{preface/Preface.tex}
|
||||
|
||||
\setcounter{page}{1}
|
||||
\pagenumbering{arabic}
|
||||
|
||||
\input{main/todo.tex}
|
||||
|
||||
%%%%%% Installation and Tool Use
|
||||
\input{installation/Install.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../installation/Install.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%%%% Crash Course
|
||||
\input{crashCourse/CrashCourse.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../crashCourse/CrashCourse.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%%%% Basic programming (milestone 2.1)
|
||||
% \input{basic/Basic.tex}
|
||||
% \commentout{
|
||||
% \begin{code}
|
||||
% include "../basic/Basic.tex";
|
||||
% \end{code}
|
||||
% }
|
||||
|
||||
%%%%%% Transposition ciphers
|
||||
\input{classic/Classic.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../classic/Classic.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%%%% Enigma
|
||||
\input{enigma/Enigma.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../enigma/Enigma.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%%%% High-assurance
|
||||
\input{highAssurance/HighAssurance.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../highAssurance/HighAssurance.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%%%% DES (milestone 2.1)
|
||||
% \input{des/DES.tex}
|
||||
% \commentout{
|
||||
% \begin{code}
|
||||
% include "../des/DES.tex";
|
||||
% \end{code}
|
||||
% }
|
||||
|
||||
%%%%%% AES
|
||||
\input{aes/AES.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../aes/AES.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%%%% SHA (milestone 2.1)
|
||||
% \input{sha/SHA.tex}
|
||||
% \commentout{
|
||||
% \begin{code}
|
||||
% include "../sha/SHA.tex";
|
||||
% \end{code}
|
||||
% }
|
||||
|
||||
%%%%%% Advanced Verification Techniques
|
||||
%\chapter{Advanced proof techniques}
|
||||
%\section{Assumed equality}
|
||||
%\section{Uninterpreted functions}
|
||||
%\section{Proving AES correct}\label{sec:proveaes}
|
||||
%In Section~\ref{sec:aescorrectattempt}, we wrote down the below
|
||||
% Cryptol theorem stating that our AES\indAES encryption/decryption
|
||||
% functions work correctly:
|
||||
%\begin{Verbatim}
|
||||
% theorem AESCorrect: {msg key}. aesDecrypt (aesEncrypt (msg, key), key) == msg;
|
||||
%\end{Verbatim}
|
||||
|
||||
% However, we were not able to do an automated proof of this fact, as
|
||||
% it is beyond the scope of what SAT-based equivalence checkers can
|
||||
% handle. In this section we will use our new tools to attack this
|
||||
% problem and actually complete the proof in a reasonable amount of
|
||||
% time.
|
||||
|
||||
%%%%%% SAT solving
|
||||
% \chapter{Using satisfiability solvers: Solving Sudoku and N-Queens
|
||||
% in Cryptol}\label{chap:usingsat}
|
||||
|
||||
%%%%%% Hardware
|
||||
% \chapter{Generating and proving hardware correct}
|
||||
|
||||
%%%%%% Pitfalls
|
||||
% \chapter{Pitfalls}
|
||||
% \section{Defaulting}\label{sec:pitfall:defaulting}
|
||||
% \todo{Talk about defaulting gotchas}
|
||||
% \section{Evaluation order}\label{sec:pitfall:evorder}
|
||||
% \todo{Talk about there's no short-circuit except for if-then-else,
|
||||
% although models might differ.}
|
||||
% \section{Theorems and safety checking}\label{sec:pitfall:thmexceptions}
|
||||
% \todo{Talk about safety failures and theorems}
|
||||
% \todo{Talk about why {\tt implies (x, y) = if x then y else False}
|
||||
% is not a substitute for {\tt if-then-else}}
|
||||
% \todo{Talk about assumeSafe}
|
||||
|
||||
%%%%%% Toolbox
|
||||
% \chapter{Programmer's toolbox}
|
||||
% \section{Pretty printing using {\tt format}}
|
||||
% \section{Debugging code using {\tt trace}}
|
||||
|
||||
%%%%%% Miscallaneous
|
||||
% \input{misc/Misc.tex}
|
||||
% \commentout{
|
||||
% \begin{code}
|
||||
% include "../misc/Misc.tex";
|
||||
% \end{code}
|
||||
% }
|
||||
|
||||
%%%%%% Conclusion (milestone 2.1)
|
||||
% \input{conclusion/Conclusion.tex}
|
||||
% \commentout{
|
||||
% \begin{code}
|
||||
% include "../conclusion/Conclusion.tex";
|
||||
% \end{code}
|
||||
% }
|
||||
|
||||
\appendix
|
||||
% \fancyhead[LO,RE]{\fancyplain{}{\textsf{\nouppercase{\leftmark}}}}
|
||||
\fancyhead[LO,RE]{\fancyplain{}{}}
|
||||
|
||||
%%%% Solutions
|
||||
\chapter{Solutions to selected exercises}
|
||||
\label{cha:solut-select-exerc}
|
||||
|
||||
As with any language, there are usually multiple ways to write the
|
||||
same function in Cryptol. We have tried to use the most idiomatic
|
||||
Cryptol code segments in our solutions. Note that Cryptol prints
|
||||
numbers out in hexadecimal by default. In most of the answers below,
|
||||
we have implicitly used the command {\tt :set base=10} to print
|
||||
numbers out in decimal for readability.\indSettingBase \shipoutAnswer
|
||||
|
||||
%%%% Cryptol primitives
|
||||
\input{prims/Primitives.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../prims/Primitives.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%% Enigma code
|
||||
\input{enigma/EnigmaCode.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../enigma/EnigmaCode.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%% AES code
|
||||
\input{aes/AESCode.tex}
|
||||
\commentout{
|
||||
\begin{code}
|
||||
include "../aes/AESCode.tex";
|
||||
\end{code}
|
||||
}
|
||||
|
||||
%%%% Grammar
|
||||
\input{appendices/grammar.tex}
|
||||
|
||||
%%%% Glossary
|
||||
\printglossary
|
||||
\addcontentsline{toc}{chapter}{Glossary}
|
||||
|
||||
%%%% Bibliography
|
||||
\bibliography{bib/cryptol}
|
||||
\bibliographystyle{plain}
|
||||
|
||||
%%%% Index
|
||||
\printindex
|
||||
|
||||
%%%% sanity checks
|
||||
% \commentout{
|
||||
% \begin{code}
|
||||
% isEverythingSane = ~zero == checks
|
||||
% where checks = [aesEncSanityCheck aesDecSanityCheck];
|
||||
% \end{code}
|
||||
% }
|
||||
|
||||
\end{document}
|
30
docs/ProgrammingCryptol/main/todo.tex
Normal file
30
docs/ProgrammingCryptol/main/todo.tex
Normal file
@ -0,0 +1,30 @@
|
||||
%\todo[inline]{}
|
||||
|
||||
\todo[inline]{2.0: Ensure consistency of use of the following terms:
|
||||
\emph{runtime}, \emph{type inference}, \emph{type checking},
|
||||
\emph{typechecker}, \emph{command line}, \emph{datatype},
|
||||
\emph{typeclass}.}
|
||||
|
||||
\todo[inline]{Replace all explicit references to environments by
|
||||
\texttt{autoref}.}
|
||||
|
||||
\todo[inline]{Ensure that all uses of \texttt{paragraph} are consistent wrt
|
||||
the use of a full stop or not.}
|
||||
|
||||
\todo[inline]{Why are we using \texttt{Verbatim} rather than
|
||||
\texttt{verbatim}?}
|
||||
|
||||
\todo[inline]{Double-check all uses of cite to ensure leading
|
||||
non-breaking space.}
|
||||
|
||||
\todo[inline]{Ensure that we use math mode for all uses of inline
|
||||
numbers that are equational. Note the subtle typographic change!}
|
||||
|
||||
\todo[inline]{Make sure all footnotes are consistent.}
|
||||
|
||||
\todo[inline]{Take a final pass to find orphans and widows.}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "Cryptol"
|
||||
%%% End:
|
1
docs/ProgrammingCryptol/misc/.gitignore
vendored
Normal file
1
docs/ProgrammingCryptol/misc/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/auto
|
91
docs/ProgrammingCryptol/misc/Misc.tex
Normal file
91
docs/ProgrammingCryptol/misc/Misc.tex
Normal file
@ -0,0 +1,91 @@
|
||||
|
||||
\chapter{Miscellaneous problems}
|
||||
|
||||
%=====================================================================
|
||||
\section{Fun problems}
|
||||
\label{sec:funproblems}
|
||||
\sectionWithAnswers{Fun problems}{sec:funproblems}
|
||||
|
||||
In this section we present a number of problems for the interested
|
||||
reader to pursue.
|
||||
|
||||
\begin{Exercise}\label{ex:misc:riffle}
|
||||
A riffle shuffle of a deck of even-numbered cards splits the deck
|
||||
into two equal parts, and then alternates the cards. That is, if the
|
||||
cards were originally numbered $1$ \ldots $10$, they will end up $1,
|
||||
6, 2, 7, 3, 8, 4, 9, 5, 10$. Write a function {\tt riffle} that
|
||||
takes an even number of elements and returns the elements in the new
|
||||
order. The signature of your function should be:
|
||||
\begin{code}
|
||||
riffle : {a b} (fin a) => [2*a]b -> [2*a]b;
|
||||
\end{code}
|
||||
You might find the following Cryptol primitive functions useful:
|
||||
\begin{Verbatim}
|
||||
width : {a b c} (c >= width a) => [a]b -> [c]
|
||||
take : {a b c} (fin a,b >= 0) => (a,[a+b]c) -> [a]c
|
||||
drop : {a b c} (fin a,a >= 0) => (a,[a+b]c) -> [b]c
|
||||
join : {a b c} [a][b]c -> [a*b]c
|
||||
\end{Verbatim}
|
||||
Use the interpreter to pass arguments to these functions to
|
||||
familiarize yourself with their operation first. What happens when you
|
||||
call {\tt riffle} with a sequence that has an odd number of elements?
|
||||
\end{Exercise}
|
||||
|
||||
\begin{Answer}\ansref{ex:misc:riffle}
|
||||
\begin{code}
|
||||
riffle xs = join [| [x y] || x <- fh || y <- sh |]
|
||||
where [fh sh] = split xs;
|
||||
\end{code}
|
||||
The Cryptol type-checker will {\em not} allow passing an odd number of
|
||||
elements to {\tt riffle}. To see the error message, issue: {\tt riffle
|
||||
[1..5]}.
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:misc:riffle2}
|
||||
Given a deck of 52 cards, 8 riffles returns the deck to its original
|
||||
position. Write a theorem stating this fact and prove it.
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:misc:riffle2}
|
||||
Note that the actual contents of the input sequence is immaterial;
|
||||
we will just use 8-bit numbers.
|
||||
\begin{code}
|
||||
riffle8 : [52][8] -> Bit;
|
||||
theorem riffle8: {deck}. decks @ 8 == deck
|
||||
where decks = [deck] # [| riffle d || d <- decks |];
|
||||
\end{code}
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:misc:sort}
|
||||
Define the merge-sort function in Cryptol, that works over arbitrary
|
||||
finite sequences of words. Prove its correctness. You might want to
|
||||
split the proof in two parts. First prove that the output is a
|
||||
permutation of the input, and then prove that the output is always
|
||||
in increasing order.
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:misc:sort}
|
||||
A solution to the merge-sort problem can be found in the {\tt
|
||||
Examples} directory of the Cryptol distribution.
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:misc:legato}
|
||||
Legato's challenge refers to the verification of an 8-bit
|
||||
multiplication algorithm encoded in Mostek assembly code. More
|
||||
information on Legato's challenge can be found at:
|
||||
\begin{center}
|
||||
\url{http://www.cs.utexas.edu/~moore/acl2/workshop-2004/contrib/legato/Weakest-Preconditions-Report.pdf}
|
||||
\end{center}
|
||||
Write a Cryptol program to model Legato's multiplication algorithm
|
||||
following the machine model. Prove that the multiplier is correct.
|
||||
\end{Exercise}
|
||||
\begin{Answer}\ansref{ex:misc:legato}
|
||||
A solution can be found at:
|
||||
\begin{center} \url{http://www.galois.com/blog/2009/07/08/legatosmultiplierincryptol}
|
||||
\end{center}
|
||||
\end{Answer}
|
||||
|
||||
\begin{Exercise}\label{ex:misc:skein}
|
||||
The Cryptol distribution comes with a variety of crypto algorithm
|
||||
implementations, including AES and the SHA-3 candidate Skein. Study
|
||||
these definitions and experiment with them using the Cryptol
|
||||
interpreter.
|
||||
\end{Exercise}
|
72
docs/ProgrammingCryptol/preface/Notice.tex
Normal file
72
docs/ProgrammingCryptol/preface/Notice.tex
Normal file
@ -0,0 +1,72 @@
|
||||
\noindent
|
||||
{\bf IMPORTANT NOTICE}
|
||||
|
||||
{\small
|
||||
This documentation is furnished for informational use only
|
||||
and is subject to change without notice. Galois, Inc.~assumes no
|
||||
responsibility or liability for any errors or inaccuracies that may
|
||||
appear in this documentation.
|
||||
|
||||
Copyright 2003--2014 Galois, Inc. All rights reserved by Galois,
|
||||
Inc.
|
||||
|
||||
This documentation, or any part of it, may not be reproduced,
|
||||
displayed, photocopied, transmitted, or otherwise copied in any form
|
||||
or by any means now known or later developed, such as electronic,
|
||||
optical, or mechanical means, without express written authorization
|
||||
from Galois, Inc.
|
||||
|
||||
Warning: This computer program and its documentation are protected
|
||||
by copyright law and international treaties. Any unauthorized
|
||||
copying or distribution of this program, its documentation, or any
|
||||
portion of it, may result in severe civil and criminal penalties,
|
||||
and will be prosecuted under the maximum extent possible under the
|
||||
law.
|
||||
|
||||
The software installed in accordance with this documentation is
|
||||
copyrighted and licensed by Galois, Inc.~under separate license
|
||||
agreement. This software may only be used pursuant to the terms and
|
||||
conditions of such license agreement. Any other use may be a
|
||||
violation of law.}
|
||||
|
||||
\noindent
|
||||
{\bf TRADEMARKS}
|
||||
|
||||
{\small
|
||||
Cryptol is a registered trademark of Galois, Inc.~in the United
|
||||
States and other countries. UNIX is a registered trademark of The
|
||||
Open Group in the U. S. and other countries. Linux is a registered
|
||||
trademark of Linus Torvalds.
|
||||
|
||||
% Solaris, Java, Java Runtime Edition, JRE, and other Java‐related marks and
|
||||
% logos are trademarks or registered trademarks of Sun Microsystems, Inc.~All
|
||||
% SPARC trademarks are used under license and are trademarks or registered
|
||||
% trademarks of SPARC International, Inc.~in the United States and other
|
||||
% countries. Products bearing SPARC trademarks are based upon an architecture
|
||||
% developed by Sun Microsystems, Inc.
|
||||
|
||||
% XILINX, the Xilinx logo, and other designated brands included herein are
|
||||
% trademarks of Xilinx, Inc.
|
||||
|
||||
Other company or product names mentioned herein may be trademarks or
|
||||
registered trademarks of their respective owners. Trademark
|
||||
specifications are subject to change without notice. All terms
|
||||
mentioned in this documentation that are known to be trademarks or
|
||||
service marks have been appropriately capitalized to the best of our
|
||||
knowledge; however, Galois cannot attest to the accuracy of all
|
||||
trademark information. Use of a term in this documentation should
|
||||
not be regarded as affecting the validity of any trademark or
|
||||
service mark.
|
||||
|
||||
\vspace{0.5in}
|
||||
\noindent
|
||||
Galois, Inc.\\
|
||||
421 SW Sixth Avenue, Suite 300 \\
|
||||
Portland, OR 97204
|
||||
}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
||||
|
60
docs/ProgrammingCryptol/preface/Preface.tex
Normal file
60
docs/ProgrammingCryptol/preface/Preface.tex
Normal file
@ -0,0 +1,60 @@
|
||||
\chapter*{Preface}
|
||||
\addcontentsline{toc}{chapter}{Preface}
|
||||
|
||||
Cryptol is a domain-specific language for programming, executing,
|
||||
testing, and formally reasoning about streams of bits. It
|
||||
particularly excels at specifying and reasoning about cryptographic
|
||||
algorithms. It has been designed to reduce the gap that currently
|
||||
exists between the {\it specification} of a cryptographic algorithm
|
||||
and its executable {\it implementation}. As a result, a well-written
|
||||
Cryptol program will look very much like the specification of the
|
||||
algorithm it implements, and is also executable.
|
||||
|
||||
Our goal in this book is to both teach you the Cryptol language and
|
||||
provide a reference text for the use of the Cryptol system. The
|
||||
Cryptol system provides: (1)~a REPL for experimentation, (2)~a parser
|
||||
and typechecker for Cryptol programs, (3)~an interpreter for executing
|
||||
Cryptol programs, (4)~automatically checking the correctness of
|
||||
Cryptol programs via randomized testing, and (5)~formally verifying
|
||||
Cryptol programs through the use of an SMT solver.
|
||||
|
||||
We demonstrate Cryptol in action via normal programming problems,
|
||||
traditional cryptographic techniques (such as substitution ciphers),
|
||||
historical cryptographic mechanisms (such as the Enigma), and modern
|
||||
algorithms (such as DES, SHA, and AES), focusing on how they are
|
||||
elegantly modeled using the Cryptol language. Since our emphasis is
|
||||
on programming, we introduce some of the techniques that are useful
|
||||
for the working programmer, including the use of Cryptol's validation
|
||||
and verification tools that directly support high-assurance
|
||||
programming.
|
||||
|
||||
Our approach is hands on. We strongly urge the reader to try out the
|
||||
material using the Cryptol toolset directly. It would be most
|
||||
effective to read this document while trying the code and interacting
|
||||
with Cryptol itself. For information on how to download and use the
|
||||
Cryptol toolset, please visit \url{www.cryptol.net}.
|
||||
|
||||
Most exercises come with solutions provided at the end. We urge the
|
||||
readers to refer to solutions as a last resort as they work through
|
||||
the exercises.
|
||||
|
||||
\note{This book covers Cryptol version 2, which is still under
|
||||
development. It is possible that the syntax and semantics for the
|
||||
language or commands will change. You may encounter bugs or
|
||||
unexpected behaviors. Please let us know if you encounter any
|
||||
problems, by sending email to {\tt cryptol@galois.com} or by
|
||||
visiting our GitHub presence linked from the Cryptol website.}
|
||||
|
||||
The authors of this book are Levent {Erk\"{o}k}, Dylan McNamee, Joseph
|
||||
Kiniry, Iavor Diatchki, and John Launchbury, with contributions from
|
||||
Magnus Carlsson, Kyle Carter, Trevor Elliott, Adam Foltzer, Brian
|
||||
Huffman, David Lazar, John Matthews, Eric Mertens, Matt Sottile, Aaron
|
||||
Tomb, and Adam Wick.
|
||||
|
||||
\todo[inline]{Replace manual use of Trac URLs with \texttt{ticket}
|
||||
macro everywhere.}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
93
docs/ProgrammingCryptol/prims/Primitives.tex
Normal file
93
docs/ProgrammingCryptol/prims/Primitives.tex
Normal file
@ -0,0 +1,93 @@
|
||||
\chapter{Cryptol primitive functions}
|
||||
|
||||
\commentout{
|
||||
\begin{code}
|
||||
primsPlaceHolder=1;
|
||||
\end{code}
|
||||
}
|
||||
|
||||
\paragraph*{Bitwise operations}
|
||||
\begin{Verbatim}
|
||||
&&, ||, ^ : {a} a -> a -> a
|
||||
~ : {a} a -> a
|
||||
\end{Verbatim}
|
||||
\paragraph*{Comparisons}
|
||||
\begin{Verbatim}
|
||||
==, != : {a} (Cmp a) => a -> a -> Bit
|
||||
<, >, <=, >= : {a} (Cmp a) => [a] -> [a] -> Bit
|
||||
\end{Verbatim}
|
||||
\paragraph*{Arithmetic}
|
||||
\begin{Verbatim}
|
||||
+, -, *, /, %, ** : {a} (Arith a) => a -> a -> a
|
||||
lg2 : {a, b} (Arith a) => a -> a
|
||||
\end{Verbatim}
|
||||
% negate : {a b} (a >= 1) => [a]b -> [a]b
|
||||
\paragraph*{Polynomial arithmetic}
|
||||
\begin{Verbatim}
|
||||
pdiv : {a, b} (fin a, fin b) => [a] -> [b] -> [a]
|
||||
pmod : {a, b} (fin a, fin b) => [a] -> [1 + b] -> [b]
|
||||
pmult : {a, b} (fin a, fin b) => [a] -> [b] -> [max 1 (a + b) - 1]
|
||||
\end{Verbatim}
|
||||
\paragraph*{Sequences}
|
||||
\begin{Verbatim}
|
||||
take : {front, back, elem} (fin front)
|
||||
=> [front + back]elem -> [front]elem
|
||||
drop : {front, back, elem} (fin front)
|
||||
=> [front + back]elem -> [front]elem
|
||||
tail : {a, b} [a+1]b -> [a]b
|
||||
# : {a, b, c} (fin a) => ([a]b,[c]b) -> [a+c]b
|
||||
join : {parts, each, a} (fin each)
|
||||
=> [parts][each]a -> [parts * each]a
|
||||
|
||||
groupBy : {each, parts, elem} (fin each)
|
||||
=> [parts * each]elem -> [parts][each]elem
|
||||
splitBy : {parts, each, elem}
|
||||
=> [parts * each]elem -> [parts][each]elem
|
||||
reverse : {a, b} (fin a) => [a]b -> [a]b
|
||||
@ : {a, b, c} ([a]b,[c]) -> b
|
||||
! : {a, b, c} (fin a) => ([a]b,[c]) -> b
|
||||
@@ : {a, b, c, d} ([a]b,[c][d]) -> [c]b
|
||||
!! : {a, b, c, d} (fin a) => ([a]b,[c][d]) -> [c]b
|
||||
width : {a, b, c} (c >= width a) => [a]b -> [c]
|
||||
\end{Verbatim}
|
||||
\paragraph*{Shifting, rotating}
|
||||
\begin{Verbatim}
|
||||
>>, <<, >>>, <<< : {a b c} (fin a,c >= lg2 a)
|
||||
=> ([a]b,[c]) -> [a]b
|
||||
\end{Verbatim}
|
||||
\paragraph*{Miscellaneous}
|
||||
\begin{Verbatim}
|
||||
zero : {a} a
|
||||
transpose : {a, b, c} [a][b]c -> [b][a]c
|
||||
min, max : {a} (fin a) => ([a],[a]) -> [a]
|
||||
\end{Verbatim}
|
||||
% parity : {a} (fin a) => [a] -> Bit
|
||||
\paragraph*{Representing exceptions}
|
||||
\begin{Verbatim}
|
||||
error : {a, b} [a][8] -> b
|
||||
undefined : {a} a
|
||||
\end{Verbatim}
|
||||
\todo[inline]{\texttt{error} and \texttt{undefined} are not covered in
|
||||
the book at the moment.}
|
||||
|
||||
\todo[inline]{What is the state of debugging (\texttt{trace},
|
||||
\texttt{ASSERT}), randomness (\texttt{random}), and pretty-printing
|
||||
(\texttt{format}) built-ins?}
|
||||
%\paragraph*{Debugging}
|
||||
%\begin{Verbatim}
|
||||
% trace : {a b c} ([a][8],b,c) -> c
|
||||
% ASSERT : {a b} (Bit,[a][8],b) -> b
|
||||
%\end{Verbatim}
|
||||
%\paragraph*{Generating random numbers}
|
||||
%\begin{Verbatim}
|
||||
% random : {a b} (32 >= a) => [a] -> b
|
||||
%\end{Verbatim}
|
||||
%\paragraph*{Pretty printing}
|
||||
%\begin{Verbatim}
|
||||
% format
|
||||
%\end{Verbatim}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
7
docs/ProgrammingCryptol/sha/SHA.tex
Normal file
7
docs/ProgrammingCryptol/sha/SHA.tex
Normal file
@ -0,0 +1,7 @@
|
||||
\chapter{SHA: The Secure Hash Algorithm}
|
||||
\label{cha:sha:-secure-hash}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
35
docs/ProgrammingCryptol/title/Title.tex
Normal file
35
docs/ProgrammingCryptol/title/Title.tex
Normal file
@ -0,0 +1,35 @@
|
||||
\noindent
|
||||
\begin{center}
|
||||
{\LARGE \bf Programming Cryptol}
|
||||
|
||||
{\it Levent Erkök\\*
|
||||
Dylan McNamee \\*
|
||||
Joe Kiniry \\*
|
||||
Iavor Diatchki \\*
|
||||
John Launchbury \\*
|
||||
}
|
||||
|
||||
\end{center}
|
||||
|
||||
\vspace{0.5in}
|
||||
\noindent
|
||||
Galois, Inc.\\
|
||||
421 SW Sixth Avenue, Suite 300 \\
|
||||
Portland, OR 97204
|
||||
|
||||
\pagebreak
|
||||
\noindent {\bf Acknowledgements}\\
|
||||
\vspace{0.5cm}
|
||||
\noindent Cryptol has been under development for over a decade with
|
||||
many people contributing to its design and implementation. Those
|
||||
people include Joel Stanley, Joe Hendrix, Aaron Tomb, Adam Wick, Jeff
|
||||
Lewis, Philip Weaver, and Sally Browning.
|
||||
|
||||
\todo[inline]{2.0: Check with R2D folks about acknowleging Brad Martin,
|
||||
Frank Taylor, and Sean Weaver.}
|
||||
|
||||
\todo[inline]{2.0: Do we include Magnus Carlson, Fergus Henderson, Joe
|
||||
Hurd, and John Matthews?}
|
||||
|
||||
\vspace{1in}
|
||||
\pagebreak
|
3
docs/ProgrammingCryptol/tools/.gitignore
vendored
Normal file
3
docs/ProgrammingCryptol/tools/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.hi
|
||||
*.o
|
||||
compileProgrammingCryptol
|
10
docs/ProgrammingCryptol/tools/Makefile
Normal file
10
docs/ProgrammingCryptol/tools/Makefile
Normal file
@ -0,0 +1,10 @@
|
||||
.PHONY: all
|
||||
all: compileProgrammingCryptol
|
||||
@./compileProgrammingCryptol
|
||||
|
||||
|
||||
compileProgrammingCryptol: compileProgrammingCryptol.hs
|
||||
@ghc --make -o $@ $<
|
||||
|
||||
clean:
|
||||
@rm -f *.hi *.o
|
180
docs/ProgrammingCryptol/tools/compileProgrammingCryptol.hs
Normal file
180
docs/ProgrammingCryptol/tools/compileProgrammingCryptol.hs
Normal file
@ -0,0 +1,180 @@
|
||||
-- |
|
||||
-- Module : $Header$
|
||||
-- Copyright : (c) 2013-2014 Galois, Inc.
|
||||
-- License : BSD3
|
||||
-- Maintainer : cryptol@galois.com
|
||||
-- Stability : provisional
|
||||
-- Portability : portable
|
||||
|
||||
{-# OPTIONS -Wall #-}
|
||||
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
||||
{-# LANGUAGE ImplicitParams #-}
|
||||
|
||||
module Main(main) where
|
||||
|
||||
import Control.Parallel.Strategies
|
||||
import Data.Char
|
||||
import Data.List
|
||||
import Numeric
|
||||
import System.Exit
|
||||
import System.IO
|
||||
import System.Timeout
|
||||
import System.Directory
|
||||
import System.FilePath
|
||||
import System.Process
|
||||
import System.Time
|
||||
|
||||
|
||||
---------------------------------------------------------------
|
||||
-- Configuration
|
||||
|
||||
targetName :: String
|
||||
targetName = "Cryptol"
|
||||
|
||||
topDir :: FilePath
|
||||
topDir = "/Volumes/Galois/Projects/CTK/Cryptol/teardrop/Documentation/ProgrammingCryptol"
|
||||
|
||||
fullTriggers :: [FilePath] -- these trigger full compile
|
||||
fullTriggers = [ "bib" </> "cryptol.bib"
|
||||
, "utils" </> "Indexes.tex"
|
||||
, "utils" </> "GlossaryItems.tex"
|
||||
]
|
||||
|
||||
-- rest is derived or should be glacial, but better checkout
|
||||
tmpDir :: FilePath
|
||||
tmpDir = "/tmp"
|
||||
|
||||
logFile :: FilePath -- latex log
|
||||
logFile = tmpDir </> targetName <.> "log"
|
||||
|
||||
target :: FilePath -- final pdf
|
||||
target = targetName <.> "pdf"
|
||||
|
||||
title :: String -- growl title
|
||||
title = targetName
|
||||
---------------------------------------------------------------
|
||||
-- utils
|
||||
ifM :: Monad m => m Bool -> m a -> m a -> m a
|
||||
ifM t tb fb = t >>= \b -> if b then tb else fb
|
||||
|
||||
whenM :: Monad m => m Bool -> m () -> m ()
|
||||
whenM t a = ifM t a (return ())
|
||||
|
||||
ignore :: Monad m => m a -> m ()
|
||||
ignore m = m >> return ()
|
||||
|
||||
modTime :: FilePath -> IO (Maybe ClockTime)
|
||||
modTime fn = fmap Just (getModificationTime fn) `catch` const (return Nothing)
|
||||
|
||||
safeSys :: IO () -> IO ()
|
||||
safeSys a = a `catch` die
|
||||
where die e = do putStrLn $ "\nException: " ++ show e
|
||||
exitWith (ExitFailure 1)
|
||||
|
||||
instance NFData ExitCode
|
||||
|
||||
timeIt :: NFData a => IO a -> IO (String, a)
|
||||
timeIt m = do start <- getClockTime
|
||||
r <- m
|
||||
end <- rnf r `seq` getClockTime
|
||||
let elapsed = diffClockTimes end start
|
||||
elapsedS = "Elapsed:" ++ showTDiff elapsed
|
||||
rnf elapsedS `seq` return (elapsedS, r)
|
||||
where showTDiff :: TimeDiff -> String
|
||||
showTDiff itd = et
|
||||
where td = normalizeTimeDiff itd
|
||||
vals = dropWhile (\(v, _) -> v == 0) (zip [tdYear td, tdMonth td, tdDay td, tdHour td, tdMin td] "YMDhm")
|
||||
sec = ' ' : show (tdSec td) ++ dropWhile (/= '.') pico
|
||||
pico = showFFloat (Just 3) (((10**(-12))::Double) * fromIntegral (tdPicosec td)) "s"
|
||||
et = concatMap (\(v, c) -> ' ':show v ++ [c]) vals ++ sec
|
||||
|
||||
growl :: (?curId :: Id) => Bool -> String -> [String] -> IO ()
|
||||
growl goaway t s = ignore $ readProcess "growlnotify" (stickyArg ++ [title, t] ++ ["-d", "Cryptol" ++ show ?curId] ++ ["-m", args]) ""
|
||||
where stickyArg | goaway = []
|
||||
| True = ["-s"]
|
||||
args = concat $ intersperse "\n" s
|
||||
---------------------------------------------------------------
|
||||
|
||||
type Id = Integer
|
||||
|
||||
main :: IO ()
|
||||
main = do hSetBuffering stdin NoBuffering
|
||||
hSetBuffering stdout NoBuffering
|
||||
hSetEcho stdout False
|
||||
safeSys $ setCurrentDirectory topDir
|
||||
let ?curId = 0 in prompt True
|
||||
|
||||
prompt :: (?curId :: Id) => Bool -> IO ()
|
||||
prompt tout = do
|
||||
let curId' = ?curId+1
|
||||
prompt' = let ?curId = curId' in prompt
|
||||
putStr $ "\r" ++ replicate 60 ' ' ++ "\r" ++ if tout then promptS else promptWS
|
||||
mbc <- (if tout then timeout 1000000 else (fmap Just)) getChar
|
||||
case fmap toUpper mbc of
|
||||
Nothing -> whenM need (ifM needFull full quick) >> prompt' True
|
||||
Just 'L' -> quick >> prompt' True
|
||||
Just 'F' -> full >> prompt' True
|
||||
Just 'C' -> prompt' True
|
||||
Just 'W' -> prompt' False
|
||||
Just 'Q' -> do putStrLn "\nTerminating.."
|
||||
exitWith ExitSuccess
|
||||
_ -> prompt' True
|
||||
where promptS, promptWS :: String
|
||||
promptS = "Action (l[atex] f[ull] w[ait] q[uit])? "
|
||||
promptWS = "Action (l[atex] f[ull] w[ait] q[uit] c[ontinue])? "
|
||||
|
||||
needFull :: IO Bool
|
||||
needFull = do mtt <- modTime target
|
||||
mtts <- mapM modTime fullTriggers
|
||||
return $ any (> mtt) mtts
|
||||
|
||||
quick :: (?curId :: Id) => IO ()
|
||||
quick = do whenM (doesFileExist target) $ removeFile target
|
||||
make "quick" ["quick"]
|
||||
|
||||
full :: (?curId :: Id) => IO ()
|
||||
full = do _ <- readProcess "make" ["superClean"] ""
|
||||
make "full" []
|
||||
|
||||
need :: IO Bool
|
||||
need = do r <- readProcess "make" ["-n"] ""
|
||||
return $ dropWhile (/= ':') r /= ": Nothing to be done for `all'.\n"
|
||||
|
||||
make :: (?curId :: Id) => String -> [String] -> IO ()
|
||||
make how args = do
|
||||
growl False "" $ ["Starting " ++ how ++ " compilation"]
|
||||
(d, ec) <- timeIt $ system $ unwords $ "make" : args
|
||||
case ec of
|
||||
ExitFailure _ -> dieErrors
|
||||
ExitSuccess -> checkWarnings d
|
||||
|
||||
dieErrors :: (?curId :: Id) => IO ()
|
||||
dieErrors = do logCts <- readFile logFile >>= return . filter (not . all isSpace) . lines
|
||||
let process (x:y:z:rest) sofar
|
||||
| take 2 y == "l." = process rest (z:y:x:sofar)
|
||||
| True = process (y:z:rest) sofar
|
||||
process _ sofar = sofar
|
||||
badLines = process logCts []
|
||||
growl False "(FAILED)" badLines
|
||||
|
||||
checkWarnings :: (?curId :: Id) => String -> IO ()
|
||||
checkWarnings d = do logLines <- readFile logFile >>= return . lines
|
||||
let badLines = filter isEither logLines
|
||||
case badLines of
|
||||
[] -> checkSpelling d
|
||||
_ -> growl False "(FAILED)" $ badLines
|
||||
where (lw, w) = (length w, "LaTeX Warning")
|
||||
(lu, u) = (length u, "undefined")
|
||||
isWarning s = any (\l -> take lw l == w) $ tails s
|
||||
isUndefined s = any (\l -> take lu l == u) $ tails s
|
||||
isEither s = isWarning s || isUndefined s
|
||||
|
||||
checkSpelling :: (?curId :: Id) => String -> IO ()
|
||||
checkSpelling d = do logCts <- readProcessWithExitCode "make" ["quickSpell"] "" >>= \(_, out, err) -> return (lines (out ++ err))
|
||||
let new = map (drop 2) $ filter (\l -> take 1 l == "<") logCts
|
||||
old = map (drop 2) $ filter (\l -> take 1 l == ">") logCts
|
||||
case new of
|
||||
[] -> case old of
|
||||
[] -> growl True "(SUCCESS)" [d]
|
||||
_ -> growl False "(SUCCESS, Fixed words)" $ old
|
||||
_ -> growl False "(FAILED Spell check)" $ new
|
38
docs/ProgrammingCryptol/tools/genAlph.hs
Normal file
38
docs/ProgrammingCryptol/tools/genAlph.hs
Normal file
@ -0,0 +1,38 @@
|
||||
-- |
|
||||
-- Module : $Header$
|
||||
-- Copyright : (c) 2013-2014 Galois, Inc.
|
||||
-- License : BSD3
|
||||
-- Maintainer : cryptol@galois.com
|
||||
-- Stability : provisional
|
||||
-- Portability : portable
|
||||
|
||||
-- alph generates a random permutation of the alphabet
|
||||
-- symAlph gives you a permutation that is symmetric (i.e., if A maps to B, then
|
||||
-- B maps to A); and also one that never maps anything back to itself.
|
||||
module GenAlph(alph, symAlph) where
|
||||
|
||||
import System.Random
|
||||
import qualified Data.Map as M
|
||||
import Control.Monad
|
||||
|
||||
letters = ['A' .. 'Z']
|
||||
|
||||
genAlph = go []
|
||||
where go xs | length xs == 26 = return xs
|
||||
| True = do s <- randomRIO (0, 25)
|
||||
if s `elem` xs then go xs else go (s:xs)
|
||||
|
||||
alph = do s <- genAlph
|
||||
return $ [letters !! i | i <- s ]
|
||||
|
||||
symAlph = do s <- foldM add M.empty letters
|
||||
return $ map snd $ M.toAscList s
|
||||
where add m l
|
||||
| l `elem` M.keys m = return m
|
||||
| True = do i <- randomRIO (0, 25)
|
||||
let e = letters !! i
|
||||
if e == l
|
||||
then add m l
|
||||
else case e `M.lookup` m of
|
||||
Nothing -> return $ M.insert l e $ M.insert e l $ m
|
||||
Just _ -> add m l
|
47
docs/ProgrammingCryptol/utils/GlossaryItems.tex
Normal file
47
docs/ProgrammingCryptol/utils/GlossaryItems.tex
Normal file
@ -0,0 +1,47 @@
|
||||
%%% NB. If you put a citation here, make sure it appears elsewhere in
|
||||
%%% the document too, otherwise bibtex won't be able to find it!
|
||||
\newcommand{\glosAES}{\glossary{name=AES, description={The Advanced
|
||||
Encryption Standard~\cite{aes}}}\xspace}
|
||||
|
||||
\newcommand{\glosFibonacci}{\glossary{name=Fibonacci numbers,
|
||||
description={The sequence $0, 1, 1, 2, 3, 5, \ldots$ After the
|
||||
elements $0$ and $1$, each consecutive element is the sum of the two
|
||||
previous numbers~\cite{wiki:fibonacci}}}\xspace}
|
||||
|
||||
\newcommand{\glosPlaintext}{\glossary{name=Plaintext, description={A
|
||||
``readable'' message that we would like to encrypt, the message in the
|
||||
clear}}\xspace}
|
||||
|
||||
\newcommand{\glosCiphertext}{\glossary{name=Ciphertext,
|
||||
description={The result of encrypting a plaintext message,
|
||||
``unreadable'' unless the key is known}}\xspace}
|
||||
|
||||
\newcommand{\glosCipherkey}{\glossary{name=Cipherkey, description={The
|
||||
key used in a particular encryption/decryption task}}\xspace}
|
||||
|
||||
\newcommand{\glosSAT}{\glossary{name=SAT Solver, description={An
|
||||
automated tool for solving boolean satisfiability problems. Cryptol
|
||||
uses SAT/SMT solvers in order to provide its high-assurance
|
||||
capabilities}}\xspace}
|
||||
|
||||
\newcommand{\glosSMT}{\glossary{name=SMT Solver,
|
||||
description={Satisfiability Modulo Theories: An automated tool for
|
||||
establishing satisfiability problems with respect to certain
|
||||
theories. One of the theories of interest to Cryptol is that of
|
||||
bit-vectors, as it provides a natural medium for translating Cryptol's
|
||||
bit-precise theorems}}\xspace}
|
||||
|
||||
\newcommand{\glosNIST}{\glossary{name=NIST, description={National
|
||||
Institute of Standards and Technology. The institution in charge of
|
||||
standardizing cryptoalgorithms (amongst many other things) in
|
||||
USA.}}\xspace}
|
||||
|
||||
\newcommand{\glosGF}{\glossary{name=GF, description={Galois Field. The
|
||||
notation GF($p^n$) stands for the finite field with $p^n$
|
||||
elements. For instance, the AES algorithm uses GF($2^8$)
|
||||
internally~\cite{wiki:galoisfield}}}\xspace}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
215
docs/ProgrammingCryptol/utils/Indexes.tex
Normal file
215
docs/ProgrammingCryptol/utils/Indexes.tex
Normal file
@ -0,0 +1,215 @@
|
||||
%
|
||||
% Programming in Cryptol
|
||||
% Galois, Inc.
|
||||
%
|
||||
|
||||
% funky symbolic things
|
||||
\newcommand{\indLamExp}{\index{000lambda@\ensuremath{\lambda}-expression}\xspace}
|
||||
|
||||
% operators
|
||||
\newcommand{\indAppend}{\index{AAAappend@\texttt{\#}, \ (append)}\xspace}
|
||||
\newcommand{\indIndex}{\index{AAAselect@\texttt{"@}, \ (select)}\xspace}
|
||||
\newcommand{\indRIndex}{\index{AAAreverseselect@\texttt{"!}, \ (reverse select)}\xspace}
|
||||
\newcommand{\indIndexs}{\index{AAAselects@\texttt{"@@}, \ (permutation)}\xspace}
|
||||
\newcommand{\indRIndexs}{\index{AAAreverseselects@\texttt{"!"!}, \ (reverse permutation)}\xspace}
|
||||
\newcommand{\indShiftLeft}{\index{AAAshiftleft@\texttt{<<}, \ (shift left)}\xspace}
|
||||
\newcommand{\indShiftRight}{\index{AAAshiftleft@\texttt{>>}, \ (shift right)}\xspace}
|
||||
\newcommand{\indRotLeft}{\index{AAArotateleft@\texttt{<<<}, \ (rotate left)}\xspace}
|
||||
\newcommand{\indRotRight}{\index{AAArotateright@\texttt{>>>}, \ (rotate right)}\xspace}
|
||||
\newcommand{\indOr}{\index{AAAor@\texttt{"|}, \ (or)}\xspace}
|
||||
\newcommand{\indAnd}{\index{AAAandand@\texttt{"\&}, \ (and)}\xspace}
|
||||
\newcommand{\indXOr}{\index{AAAxor@\texttt{\;\;"\^}, \ (xor)}\xspace}
|
||||
\newcommand{\indComplement}{\index{AAAcomplement@\texttt{\;\;"\~}, \ (complement)}\xspace}
|
||||
\newcommand{\indPlus}{\index{AAAplus@\texttt{"+}, \ (add)}\xspace}
|
||||
\newcommand{\indMinus}{\index{AAAminus@\texttt{"-}, \ (subtract)}\xspace}
|
||||
\newcommand{\indExponentiate}{\index{AAAexponentiate@\texttt{"*"*}, \ (exponentiate)}\xspace}
|
||||
\newcommand{\indUnaryMinus}{\index{AAAunaryMinus@\texttt{"-}, \ (unary minus)}\xspace}
|
||||
\newcommand{\indTimes}{\index{AAAtimes@\texttt{"*}, \ (multiply)}\xspace}
|
||||
\newcommand{\indDiv}{\index{AAAdiv@\texttt{"/}, \ (divide)}\xspace}
|
||||
\newcommand{\indMod}{\index{AAAmod@\texttt{"\%}, \ (modulus)}\xspace}
|
||||
\newcommand{\indEq}{\index{AAAequals@\texttt{"="=}, \ (equal)}\xspace}
|
||||
\newcommand{\indNeq}{\index{AAequalsnot@\texttt{"!"=}, \ (not-equal)}\xspace}
|
||||
\newcommand{\indGt}{\index{AAAgreaterthan@\texttt{">}, \ (greater than)}\xspace}
|
||||
\newcommand{\indGte}{\index{AAAgreaterthanorequal@\texttt{">=}, \ (greater or equal)}\xspace}
|
||||
\newcommand{\indLt}{\index{AAAlessthan@\texttt{"<}, \ (less than)}\xspace}
|
||||
\newcommand{\indLte}{\index{AAAlessthanorequal@\texttt{"<=}, \ (less or equal)}\xspace}
|
||||
\newcommand{\indUnderscore}{\index{AAAunderscore@\texttt{\_}, \ (underscore)}\xspace}
|
||||
|
||||
% settings
|
||||
\newcommand{\indSettingASCII}{\index{settings!\texttt{a},\ (ASCII printing)}\xspace}
|
||||
\newcommand{\indSettingType}{\index{settings!\texttt{t},\ (printing types)}\xspace}
|
||||
\newcommand{\indSettingBase}{\index{settings!\texttt{base},\ (output base)}\xspace}
|
||||
\newcommand{\indSettingEditor}{\index{settings!\texttt{editor},\ (file editor)}\xspace}
|
||||
\newcommand{\indSettingDefaulting}{\index{settings!\texttt{d},\ (defaulting)}\xspace}
|
||||
\newcommand{\indSBV}{\index{settings!\texttt{sbv}}\xspace}
|
||||
\newcommand{\indQCCount}{\index{settings!\texttt{quickCheckCount}}\xspace}
|
||||
|
||||
% types
|
||||
\newcommand{\indTheBitType}{\index{bit}\xspace}
|
||||
\newcommand{\indTheTupleType}{\index{tuple}\xspace}
|
||||
\newcommand{\indTheWordType}{\index{word}\xspace}
|
||||
\newcommand{\indTheSequenceType}{\index{sequence}\xspace}
|
||||
\newcommand{\indTheRecordType}{\index{record}\xspace}
|
||||
\newcommand{\indTheStringType}{\index{string}\xspace}
|
||||
\newcommand{\indTheCharType}{\index{characters}\xspace}
|
||||
|
||||
% concepts
|
||||
\newcommand{\indArbitraryPrecision}{\index{word!arbitrary precision}\xspace}
|
||||
\newcommand{\indFiniteSeq}{\index{sequence!finite}\xspace}
|
||||
\newcommand{\indNestedComp}{\index{sequence!nested}\xspace}
|
||||
\newcommand{\indInfSeq}{\index{sequence!infinite}\xspace}
|
||||
\newcommand{\indStream}{\index{streams}\xspace}
|
||||
\newcommand{\indStreamEquation}{\index{stream equations}\xspace}
|
||||
\newcommand{\indEnum}{\index{sequence!enumerations}\xspace}
|
||||
\newcommand{\indCartesian}{\index{sequence!cartesian}\xspace}
|
||||
\newcommand{\indParallel}{\index{sequence!parallel}\xspace}
|
||||
\newcommand{\indComp}{\index{sequence!comprehensions}\xspace}
|
||||
\newcommand{\indArithLift}{\index{sequence!arithmetic lifting}\xspace}
|
||||
\newcommand{\indEndianness}{\index{endianness}\xspace}
|
||||
\newcommand{\indOverflow}{\index{overflow}\xspace}
|
||||
\newcommand{\indUnderflow}{\index{underflow}\xspace}
|
||||
\newcommand{\indModular}{\index{modular arithmetic}\xspace}
|
||||
\newcommand{\indFloatingPoint}{\index{floating point}\xspace}
|
||||
\newcommand{\indTypeInference}{\index{type!inference}\xspace}
|
||||
\newcommand{\indPolymorphism}{\index{type!polymorphism}\xspace}
|
||||
\newcommand{\indMonomorphism}{\index{type!monomorphism}\xspace}
|
||||
\newcommand{\indOverloading}{\index{type!overloading}\xspace}
|
||||
\newcommand{\indUndecidable}{\index{type!undecidable}\xspace}
|
||||
\newcommand{\indPredicates}{\index{type!predicates}\xspace}
|
||||
\newcommand{\indTypeClasses}{\index{type!type classes}\xspace}
|
||||
\newcommand{\indTypeVariables}{\index{type!type variables}\xspace}
|
||||
\newcommand{\indTypeContext}{\index{type!type context}\xspace}
|
||||
\newcommand{\indTypeInline}{\index{type!inline argument types}\xspace}
|
||||
\newcommand{\indTypePositionalArguments}{\index{type!positional arguments}\xspace}
|
||||
\newcommand{\indAmbiguity}{\index{type!ambiguous}\xspace}
|
||||
\newcommand{\indSignature}{\index{type!signature}\xspace}
|
||||
\newcommand{\indTypeAnnotation}{\index{type!annotation}\xspace}
|
||||
\newcommand{\indFin}{\index{type!\texttt{fin}}\xspace}
|
||||
\newcommand{\indInf}{\index{type!\texttt{inf}}\xspace}
|
||||
\newcommand{\indDefaulting}{\index{type!defaulting}\xspace}
|
||||
\newcommand{\indRecurrence}{\index{recurrences}\xspace}
|
||||
\newcommand{\indRecursion}{\index{recursion}\xspace}
|
||||
\newcommand{\indFold}{\index{fold}\xspace}
|
||||
\newcommand{\indWhileLoop}{\index{while loop}\xspace}
|
||||
\newcommand{\indPatMatch}{\index{pattern matching}\xspace}
|
||||
\newcommand{\indProperty}{\index{properties}\xspace}
|
||||
\newcommand{\indThmFuncCorr}{\index{properties!function correspondence}\xspace}
|
||||
\newcommand{\indThmCond}{\index{properties!conditional}\xspace}
|
||||
\newcommand{\indThmPolyvalid}{\index{properties!polymorphic validity}\xspace}
|
||||
\newcommand{\indQED}{\index{properties!\texttt{Q.E.D.}}\xspace}
|
||||
\newcommand{\indContradiction}{\index{properties!\texttt{contradiction}}\xspace}
|
||||
\newcommand{\indProve}{\index{properties!proving}\xspace}
|
||||
\newcommand{\indProofCompleteness}{\index{properties!completeness}\xspace}
|
||||
\newcommand{\indCounterExample}{\index{properties!counter-example}\xspace}
|
||||
\newcommand{\indSat}{\index{satisfiability checking}\xspace}
|
||||
\newcommand{\indSafe}{\index{safety checking}\xspace}
|
||||
\newcommand{\indImport}{\index{import directive}\xspace}
|
||||
\newcommand{\indPrivate}{\index{private qualifier}\xspace}
|
||||
\newcommand{\indModuleSystem}{\index{module system}\xspace}
|
||||
|
||||
% syntax
|
||||
\newcommand{\indCaseSensitive}{\index{case sensitivity}\xspace}
|
||||
\newcommand{\indLiterateProgramming}{\index{literate programming}\xspace}
|
||||
\newcommand{\indComments}{\index{comments}\xspace}
|
||||
\newcommand{\indFunApp}{\index{function application}\xspace}
|
||||
\newcommand{\indWhere}{\index{where clause}\xspace}
|
||||
\newcommand{\indTypSynonym}{\index{type synonym}\xspace}
|
||||
\newcommand{\indTSWord}{\index{type synonym!Word}\xspace}
|
||||
\newcommand{\indTSString}{\index{type synonym!String}\xspace}
|
||||
\newcommand{\indTSBool}{\index{type synonym!Bool}\xspace}
|
||||
|
||||
% constants-functions
|
||||
\newcommand{\indTrue}{\index{True@\texttt{True}}\xspace}
|
||||
\newcommand{\indFalse}{\index{False@\texttt{False}}\xspace}
|
||||
\newcommand{\indTake}{\index{take@\texttt{take}}\xspace}
|
||||
\newcommand{\indTail}{\index{tail@\texttt{tail}}\xspace}
|
||||
\newcommand{\indDrop}{\index{drop@\texttt{drop}}\xspace}
|
||||
\newcommand{\indJoin}{\index{join@\texttt{join}}\xspace}
|
||||
\newcommand{\indSplit}{\index{split@\texttt{split}}\xspace}
|
||||
\newcommand{\indSplitBy}{\index{splitBy@\texttt{splitBy}}\xspace}
|
||||
\newcommand{\indGroup}{\index{group@\texttt{group}}\xspace}
|
||||
\newcommand{\indTranspose}{\index{transpose@\texttt{transpose}}\xspace}
|
||||
\newcommand{\indTupleProj}{\index{project@\texttt{project}}\xspace}
|
||||
\newcommand{\indLg}{\index{lg2@\texttt{lg2}}\xspace}
|
||||
\newcommand{\indMin}{\index{min@\texttt{min}}\xspace}
|
||||
\newcommand{\indMax}{\index{max@\texttt{max}}\xspace}
|
||||
\newcommand{\indReverse}{\index{reverse@\texttt{reverse}}\xspace}
|
||||
\newcommand{\indWidth}{\index{width@\texttt{width}}\xspace}
|
||||
\newcommand{\indError}{\index{error@\texttt{error}}\xspace}
|
||||
\newcommand{\indUndefined}{\index{undefined@\texttt{undefined}}\xspace}
|
||||
\newcommand{\indAssert}{\index{ASSERT@\texttt{ASSERT}}\xspace}
|
||||
\newcommand{\indZero}{\index{zero@\texttt{zero}}\xspace}
|
||||
\newcommand{\indAll}{\index{all@\texttt{all}}\xspace}
|
||||
\newcommand{\indElem}{\index{elem@\texttt{elem}}\xspace}
|
||||
\newcommand{\indAny}{\index{any@\texttt{any}}\xspace}
|
||||
\newcommand{\indPoly}{\index{polynomial}\xspace}
|
||||
\newcommand{\indDivPoly}{\index{polynomial!division}\xspace}
|
||||
\newcommand{\indModPoly}{\index{polynomial!modulus}\xspace}
|
||||
\newcommand{\indMulPoly}{\index{polynomial!multiplication}\xspace}
|
||||
\newcommand{\indAddPoly}{\index{polynomial!addition}\xspace}
|
||||
\newcommand{\indSubPoly}{\index{polynomial!subtraction}\xspace}
|
||||
\newcommand{\indIrredPoly}{\index{polynomial!irreducable}\xspace}
|
||||
|
||||
% commands
|
||||
\newcommand{\indCmdBrowse}{\index{commands!browse@\texttt{:b}\ (browse)}\xspace}
|
||||
\newcommand{\indCmdLoad}{\index{commands!load@\texttt{:l}\ (load)}\xspace}
|
||||
\newcommand{\indCmdReload}{\index{commands!reload@\texttt{:r}\ (reload)}\xspace}
|
||||
\newcommand{\indCmdType}{\index{commands!type@\texttt{:t}\ (type)}\xspace}
|
||||
\newcommand{\indCmdShell}{\index{commands!shell@\texttt{"!}\ (shell)}\xspace}
|
||||
\newcommand{\indCmdEdit}{\index{commands!edit@\texttt{:e}\ (edit)}\xspace}
|
||||
\newcommand{\indCmdHelp}{\index{commands!help@\texttt{:?}\ (help)}\xspace}
|
||||
\newcommand{\indCmdQuit}{\index{commands!quit@\texttt{:q}\ (quit)}\xspace}
|
||||
\newcommand{\indCmdPrint}{\index{commands!print@\texttt{:p}\ (print)}\xspace}
|
||||
\newcommand{\indCmdInfo}{\index{commands!info@\texttt{:i}\ (info)}\xspace}
|
||||
\newcommand{\indCmdProve}{\index{commands!prove@\texttt{:prove}}\xspace}
|
||||
\newcommand{\indCmdCheck}{\index{commands!check@\texttt{:check}}\xspace}
|
||||
\newcommand{\indCmdAutoCheck}{\index{commands!check@\texttt{:check}!automatic}\xspace}
|
||||
\newcommand{\indCmdSat}{\index{commands!sat@\texttt{:sat}}\xspace}
|
||||
\newcommand{\indCmdSafe}{\index{commands!safe@\texttt{:safe}}\xspace}
|
||||
\newcommand{\indCmdLoadModule}{\index{commands!module@\texttt{:m}\ (module load)}\xspace}
|
||||
|
||||
% other
|
||||
\newcommand{\indLineCont}{\index{command line!line continuation}\xspace}
|
||||
\newcommand{\indCompletion}{\index{command line!completion}\xspace}
|
||||
|
||||
% non-Cryptol concepts
|
||||
\newcommand{\indCipherkey}{\index{cipherkey}\xspace}
|
||||
\newcommand{\indCiphertext}{\index{ciphertext}\xspace}
|
||||
\newcommand{\indPlaintext}{\index{plaintext}\xspace}
|
||||
\newcommand{\indShiftcipher}{\index{shift cipher}\xspace}
|
||||
\newcommand{\indCaesarscipher}{\index{Caesar's cipher}\xspace}
|
||||
\newcommand{\indVigenere}{\index{Vigen\`{e}re cipher}\xspace}
|
||||
\newcommand{\indTranspositioncipher}{\index{transposition cipher}\xspace}
|
||||
\newcommand{\indScytale}{\index{scytale}\xspace}
|
||||
\newcommand{\indAtbash}{\index{atbash}\xspace}
|
||||
\newcommand{\indRailFence}{\index{rail fence cipher}\xspace}
|
||||
\newcommand{\indKnownPTAttack}{\index{known plaintext attack}\xspace}
|
||||
\newcommand{\indSubstitutioncipher}{\index{substitution cipher}\xspace}
|
||||
\newcommand{\indMonoAlphSubst}{\index{substitution cipher!monoalphabetic}\xspace}
|
||||
\newcommand{\indPolyAlphSubst}{\index{substitution cipher!polyalphabetic}\xspace}
|
||||
\newcommand{\indPolyGraphSubst}{\index{substitution cipher!polygraphic}\xspace}
|
||||
\newcommand{\indSubstPeriod}{\index{substitution cipher!period}\xspace}
|
||||
\newcommand{\indEnigma}{\index{Enigma machine}\xspace}
|
||||
\newcommand{\indEnigmaPlugboard}{\index{Enigma machine!plugboard}\xspace}
|
||||
\newcommand{\indEnigmaRotor}{\index{Enigma machine!rotor}\xspace}
|
||||
\newcommand{\indEnigmaReflector}{\index{Enigma machine!reflector}\xspace}
|
||||
\newcommand{\indSymKey}{\index{symmetric key}\xspace}
|
||||
\newcommand{\indAES}{\index{AES}\xspace}
|
||||
\newcommand{\indGF}{\index{Galois field}\xspace}
|
||||
\newcommand{\indAESState}{\index{AES!state}\xspace}
|
||||
\newcommand{\indAESSbox}{\index{AES!SubBytes@\texttt{SubBytes}}\xspace}
|
||||
\newcommand{\indAESInvSbox}{\index{AES!InvSubBytes@\texttt{InvSubBytes}}\xspace}
|
||||
\newcommand{\indAESShiftRows}{\index{AES!ShiftRows@\texttt{ShiftRows}}\xspace}
|
||||
\newcommand{\indAESInvShiftRows}{\index{AES!InvShiftRows@\texttt{InvShiftRows}}\xspace}
|
||||
\newcommand{\indAESMixColumns}{\index{AES!MixColumns@\texttt{MixColumns}}\xspace}
|
||||
\newcommand{\indAESInvMixColumns}{\index{AES!InvMixColumns@\texttt{InvMixColumns}}\xspace}
|
||||
|
||||
% external tools
|
||||
\newcommand{\indABC}{\index{ABC}\xspace}
|
||||
\newcommand{\indYices}{\index{Yices}\xspace}
|
||||
\newcommand{\indIsabelleHOL}{\index{Isabelle/HOL}\xspace}
|
||||
|
||||
%%% Local Variables:
|
||||
%%% mode: latex
|
||||
%%% TeX-master: "../main/Cryptol"
|
||||
%%% End:
|
659
docs/ProgrammingCryptol/utils/exercise.sty
Normal file
659
docs/ProgrammingCryptol/utils/exercise.sty
Normal file
@ -0,0 +1,659 @@
|
||||
%% This is a slightly older version of exercise.sty; hacked to add commands
|
||||
%% AnswerBoxSectionMark and AnswerBoxExecute, and some other mods
|
||||
%% The newer version of exercise.sty breaks the type-setting, and it's not worth trying to fix it!
|
||||
|
||||
%%
|
||||
%% This is file `exercise.sty',
|
||||
%% generated with the docstrip utility.
|
||||
%%
|
||||
%% The original source files were:
|
||||
%%
|
||||
%% exercise.dtx (with options: `package')
|
||||
%%
|
||||
%% This is a generated file.
|
||||
%%
|
||||
%% Copyright (C) 2003 by Paul Pichaureau
|
||||
%%
|
||||
%% 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
|
||||
%% 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
%% Public LaTeX Project Public
|
||||
%%
|
||||
|
||||
\NeedsTeXFormat{LaTeX2e}[1999/12/01]
|
||||
\ProvidesPackage{utils/exercise}
|
||||
[2004/09/05 v1.1 Exercise package (P.Pichaureau)]
|
||||
%% \CharacterTable
|
||||
%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
|
||||
%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
|
||||
%% Digits \0\1\2\3\4\5\6\7\8\9
|
||||
%% Exclamation \! Double quote \" Hash (number) \#
|
||||
%% Dollar \$ Percent \% Ampersand \&
|
||||
%% Acute accent \' Left paren \( Right paren \)
|
||||
%% Asterisk \* Plus \+ Comma \,
|
||||
%% Minus \- Point \. Solidus \/
|
||||
%% Colon \: Semicolon \; Less than \<
|
||||
%% Equals \= Greater than \> Question mark \?
|
||||
%% Commercial at \@ Left bracket \[ Backslash \\
|
||||
%% Right bracket \] Circumflex \^ Underscore \_
|
||||
%% Grave accent \` Left brace \{ Vertical bar \|
|
||||
%% Right brace \} Tilde \~}
|
||||
%%
|
||||
\newif\if@AnswerOutput \@AnswerOutputtrue
|
||||
\newif\if@AnswerDelay \@AnswerDelayfalse
|
||||
\newif\if@ExerciseOutput \@ExerciseOutputtrue
|
||||
\newif\if@ExerciseDelay \@ExerciseDelayfalse
|
||||
\newif\if@AswLastExe \@AswLastExefalse
|
||||
|
||||
\DeclareOption{noanswer} {\@AnswerOutputfalse}
|
||||
\DeclareOption{answeronly} {\@ExerciseOutputfalse}
|
||||
\DeclareOption{noexercise} {\@ExerciseOutputfalse}
|
||||
\DeclareOption{exerciseonly} {\@AnswerOutputfalse}
|
||||
\DeclareOption{outputnothing}{\@ExerciseOutputfalse\@AnswerOutputfalse}
|
||||
\DeclareOption{exercisedelayed}{\@ExerciseDelaytrue}
|
||||
\DeclareOption{answerdelayed}{\@AnswerDelaytrue}
|
||||
\DeclareOption{lastexercise} {\@AswLastExetrue}
|
||||
\newif\if@ShowLabel \@ShowLabelfalse
|
||||
\DeclareOption{showlabel} {\@ShowLabeltrue}
|
||||
|
||||
\ProcessOptions
|
||||
\RequirePackage{keyval, ifthen}
|
||||
\def\ExerciseName{Exercise}%
|
||||
\def\AnswerName{Answer}%
|
||||
\def\ExerciseListName{Ex.}%
|
||||
\def\AnswerListName{Answer}%
|
||||
\def\ExePartName{Part}%
|
||||
\@ifpackageloaded{babel}{
|
||||
\addto{\captionsfrenchb}{
|
||||
\def\ExerciseName{Exercice}%
|
||||
\def\AnswerName{Solution}%
|
||||
\def\ExerciseListName{Ex.}%
|
||||
\def\AnswerListName{Sol.}%
|
||||
\def\ExePartName{Partie}%
|
||||
}}{}
|
||||
\newlength{\Exesep}
|
||||
\setlength{\Exesep}{1\baselineskip}
|
||||
\newlength{\Exetopsep}
|
||||
\setlength{\Exetopsep}\z@
|
||||
\newlength{\Exeparsep}
|
||||
\setlength{\Exeparsep}{\parskip}
|
||||
\newlength{\Exepartopsep}
|
||||
\setlength{\Exepartopsep}\z@
|
||||
\newlength{\Exeleftmargin}
|
||||
\setlength{\Exeleftmargin}\z@
|
||||
\newlength{\Exerightmargin}
|
||||
\setlength{\Exerightmargin}\z@
|
||||
\newlength{\Exelabelwidth}
|
||||
\setlength{\Exelabelwidth}\z@
|
||||
\newlength{\Exelabelsep}
|
||||
\setlength{\Exelabelsep}\z@
|
||||
\newlength{\ExerciseBefore}
|
||||
\setlength{\ExerciseBefore}{0em}
|
||||
\newlength{\QuestionBefore}
|
||||
\setlength{\QuestionBefore}{.25em}
|
||||
\newlength{\subQuestionBefore}
|
||||
\setlength{\subQuestionBefore}{0em}
|
||||
\newlength{\subsubQuestionBefore}
|
||||
\setlength{\subsubQuestionBefore}{0em}
|
||||
\newlength{\QuestionIndent}
|
||||
\setlength{\QuestionIndent}{3em}
|
||||
\newlength{\subQuestionIndent}
|
||||
\setlength{\subQuestionIndent}{2em}
|
||||
\newlength{\subsubQuestionIndent}
|
||||
\setlength{\subsubQuestionIndent}{2.5em}
|
||||
\newcounter{Exercise}
|
||||
\gdef\@ExerciseCounter{Exercise} %default exercise counter
|
||||
\newcounter{ExePart}[Exercise]
|
||||
\newcounter{Question}[Exercise]
|
||||
\newcounter{subQuestion}[Question]
|
||||
\newcounter{subsubQuestion}[subQuestion]
|
||||
\renewcommand{\theExercise}{\arabic{\@ExerciseCounter}}
|
||||
\renewcommand{\theExePart}{\Roman{ExePart}}
|
||||
\renewcommand{\theQuestion}{\arabic{Question}}
|
||||
\renewcommand{\thesubQuestion}{\alph{subQuestion}}
|
||||
\renewcommand{\thesubsubQuestion}{\roman{subsubQuestion}}
|
||||
\newcounter{savedQuestion}
|
||||
\newcounter{savedsubQuestion}
|
||||
\newcounter{savedsubsubQuestion}
|
||||
\def\marker#1#2{\@tempcnta#2\whiledo{\@tempcnta>0}{#1\advance
|
||||
\@tempcnta by -1 }}
|
||||
\def\DifficultyMarker{*}
|
||||
\newcommand{\ExerciseHeaderTitle}{\qquad \ExerciseTitle}
|
||||
\newcommand{\ExerciseHeaderDifficulty}{\theExerciseDifficulty\ }
|
||||
\newcommand{\ExerciseHeaderOrigin}{%
|
||||
\ ({\usefont{\encodingdefault}{\rmdefault}{m}{it}\ExerciseOrigin})}
|
||||
\newcommand{\ExerciseHeaderNB}{\ \theExercise}
|
||||
\newcommand{\ExerciseHeaderLabel}{\fbox{\textsc{\ExerciseLabel}}}
|
||||
\newcommand{\ExerciseHeader}{\centerline{%
|
||||
\textbf{\large\ExerciseHeaderDifficulty\ExerciseName%
|
||||
\ExerciseHeaderNB\ExerciseHeaderTitle\ExerciseHeaderOrigin}}\medskip}
|
||||
\newcommand{\ExerciseListHeader}{\ExerciseHeaderDifficulty%
|
||||
\textbf{\ExerciseListName\ExerciseHeaderNB%
|
||||
\ --- \ \ExerciseHeaderTitle}%
|
||||
\ExerciseHeaderOrigin\ignorespaces}
|
||||
\newcommand{\ExePartHeaderNB}{\ \theExePart}
|
||||
\newcommand{\ExePartHeaderTitle}{\quad --- \quad {\ExePartTitle}}
|
||||
\newcommand{\ExePartHeaderDifficulty}{\theExePartDifficulty\ }
|
||||
\newcommand{\ExePartHeader}{%
|
||||
\medskip\centerline{\emph{\large\ExePartHeaderDifficulty\ExePartName%
|
||||
\ExePartHeaderNB\ExePartHeaderTitle}}}
|
||||
\newcommand{\ExePartListHeader}{\bigskip%
|
||||
\emph{\ExePartHeaderDifficulty\ExePartName%
|
||||
\ExePartHeaderNB\ExePartHeaderTitle}\par\medskip}
|
||||
\newcommand{\QuestionNB}{\arabic{Question}.\ }
|
||||
\newcommand{\QuestionHeaderTitle}{\emph{(\QuestionTitle)}\ }
|
||||
\newcommand{\QuestionHeaderDifficulty}{\theQuestionDifficulty\ }
|
||||
\newcommand{\theQuestionDifficulty}{\marker{\DifficultyMarker}%
|
||||
{\QuestionDifficulty}}
|
||||
\newcommand{\subQuestionNB}{\alph{subQuestion})}
|
||||
\newcommand{\subQuestionHeaderTitle}{\emph{(\subQuestionTitle)}\ }
|
||||
\newcommand{\subQuestionHeaderDifficulty}{\thesubQuestionDifficulty\ }
|
||||
\newcommand{\subQuestionHeader}{\subQuestionHeaderDifficulty%
|
||||
\subQuestionNB)\ \emph{\subQuestionHeaderTitle}}
|
||||
\newcommand{\thesubQuestionDifficulty}{\marker{\DifficultyMarker}%
|
||||
{\subQuestionDifficulty}}
|
||||
\newcommand{\subsubQuestionNB}{\roman{subsubQuestion} -- }
|
||||
\newcommand{\subsubQuestionHeaderTitle}{\emph{(\subsubQuestionTitle)}\ }
|
||||
\newcommand{\subsubQuestionHeaderDifficulty}{\thesubsubQuestionDifficulty\ }
|
||||
\newcommand{\subsubQuestionHeader}{\subsubQuestionHeaderDifficulty%
|
||||
\subsubQuestionNB \emph{\subsubQuestionHeaderTitle} --}
|
||||
\newcommand{\thesubsubQuestionDifficulty}{%
|
||||
\marker{\DifficultyMarker}{\subsubQuestionDifficulty}}
|
||||
\newcount\@QuestionLevel \@QuestionLevel=0
|
||||
\newcommand{\the@QuestionLevel}{\number\@QuestionLevel}
|
||||
\newbox\@Exercisebox
|
||||
\newbox\all@Exercisebox
|
||||
\newbox\temp@Exercisebox
|
||||
\newbox\all@Answerbox
|
||||
\newbox\temp@Answerbox
|
||||
\newif\if@echapq \@echapqfalse
|
||||
\newif\if@Answer \@Answerfalse
|
||||
\def\termineliste#1{\global\@echapqfalse%
|
||||
\whiledo{\@QuestionLevel>#1}%
|
||||
{\ifnum\@QuestionLevel=\colonnesLevel\end{multicols}\colonnesLevel=-10\fi%
|
||||
\end{list}\advance\@QuestionLevel by -1}%
|
||||
\ifnum\@QuestionLevel=\colonnesLevel\end{multicols}\colonnesLevel=-10\fi}
|
||||
\newif\if@ExeTitle \@ExeTitlefalse
|
||||
\newif\if@ExeReName \@ExeReNamefalse
|
||||
\global\newcount\ExerciseDifficulty \ExerciseDifficulty=0
|
||||
\newif\if@ExeDifficulty \@ExeDifficultyfalse
|
||||
\newif\if@ExeOrigin \@ExeOriginfalse
|
||||
\newif\if@ExeLabel \@ExeLabelfalse
|
||||
\newif\if@ExeNB \@ExeNBfalse
|
||||
\def\theExerciseDifficulty{\marker{\DifficultyMarker}{\ExerciseDifficulty}}
|
||||
\define@key{PPExercise}{title}%
|
||||
{\global\@ExeTitletrue\gdef\ExerciseTitle{\string#1}}
|
||||
\define@key{PPExercise}{difficulty}%
|
||||
{\global\@ExeDifficultytrue\global\ExerciseDifficulty=\number#1}
|
||||
\define@key{PPExercise}{name}%
|
||||
{\global\@ExeReNametrue\gdef\@ExerciseName{\string#1}}
|
||||
\define@key{PPExercise}{origin}%
|
||||
{\global\@ExeOrigintrue\gdef\ExerciseOrigin{#1}}
|
||||
\define@key{PPExercise}{counter}%
|
||||
{\gdef\@ExerciseCounter{\string#1}}
|
||||
\define@key{PPExercise}{label}%
|
||||
{\global\@ExeLabeltrue\gdef\ExerciseLabel{\string#1}\gdef\ExerciseTrueLabel{#1}}
|
||||
\define@key{PPExercise}{number}%
|
||||
{\global\@ExeNBtrue\gdef\ExerciseLocalNB{\string#1}}
|
||||
%% \define@key{PPExercise}{domain}{}
|
||||
%% \define@key{PPExercise}{sdomain}{}
|
||||
%% \define@key{PPExercise}{keyword}{}
|
||||
\newif\if@ExeStared
|
||||
\newif\if@staredpb
|
||||
\newif\if@staredpart
|
||||
\newif\if@renamepart
|
||||
\@ExeStaredfalse
|
||||
\@staredpbfalse
|
||||
\@staredpartfalse
|
||||
\@renamepartfalse
|
||||
\def\@InitExe{\@savemathindent\global\@echapqfalse%
|
||||
\gdef\ExerciseTitle{}%
|
||||
\gdef\@ExerciseName{}%
|
||||
\gdef\ExerciseOrigin{}%
|
||||
\gdef\ExerciseTrueLabel{}%
|
||||
\global\ExerciseDifficulty=0%
|
||||
\global\@ExeTitlefalse%
|
||||
\global\@ExeReNamefalse%
|
||||
\global\@ExeDifficultyfalse%
|
||||
\global\@ExeOriginfalse%
|
||||
\global\@ExeNBfalse%
|
||||
\gdef\@ExerciseCounter{Exercise}%
|
||||
\setcounter{ExePart}{0}%
|
||||
\setcounter{Question}{0}%
|
||||
\global\@ExeLabelfalse}
|
||||
\def\@getExerciseInfo{%
|
||||
\if@ExeReName\def\ExerciseName{\@ExerciseName}\fi%
|
||||
\if@ExeTitle\else\def\ExerciseHeaderTitle{}\fi%
|
||||
\if@ExeOrigin\else\def\ExerciseHeaderOrigin{}\fi%
|
||||
\if@ExeLabel\else\def\ExerciseHeaderLabel{}\fi%
|
||||
\if@ExeDifficulty\else\def\ExerciseHeaderDifficulty{}\fi%
|
||||
\if@ExeStared\def\ExerciseHeaderNB{}\fi%
|
||||
\if@ExeNB\def\theExercise{\ExerciseLocalNB}\fi%
|
||||
\if@ExeLabel\label{\ExerciseLabel}\recordExerciseLabel{\ExerciseLabel}\fi%
|
||||
}
|
||||
\def\refstepExecounter{\if@ExeStared\else\if@ExeNB\else%
|
||||
\refstepcounter{\@ExerciseCounter}\fi\fi}
|
||||
\def\recordExerciseLabel#1{\@bsphack
|
||||
\protected@write\@auxout{}%
|
||||
{\string\newlabel{PP#1}{{\@AnswerHeaderRef}{\thepage}}}%
|
||||
\@esphack}
|
||||
\def\@BeginExeBox{\global\setbox\@Exercisebox\vbox\bgroup}
|
||||
\def\@EndExeBox{\egroup\if@Answer\if@AnswerOutput\@DelayAnswerBox\fi%
|
||||
\else\if@ExerciseOutput\@DelayExerciseBox\fi\fi}
|
||||
\def\AnswerBoxSectionMark#1{%
|
||||
\global\setbox\temp@Answerbox%
|
||||
\vbox{\unvbox\all@Answerbox\vskip\Exesep%
|
||||
\section*{\vspace*{.5em}\hrule\hrule\vspace*{.5em}\hspace*{-\parindent}#1\vspace*{.5em}\hrule\hrule\markboth{#1}{}}%
|
||||
\unvbox\@Exercisebox\vskip\z@}%
|
||||
\global\setbox\all@Answerbox\copy\temp@Answerbox%
|
||||
}
|
||||
\def\AnswerBoxExecute#1{%
|
||||
\global\setbox\temp@Answerbox%
|
||||
\vbox{\unvbox\all@Answerbox#1\unvbox\@Exercisebox}%
|
||||
\global\setbox\all@Answerbox\copy\temp@Answerbox%
|
||||
}
|
||||
\def\@DelayAnswerBox{%
|
||||
\if@ShipThisExercise\if@AnswerDelay\global\setbox\temp@Answerbox%
|
||||
\vbox{\unvbox\all@Answerbox\vskip\Exesep\unvbox\@Exercisebox\vskip\z@}%
|
||||
\global\setbox\all@Answerbox\copy\temp@Answerbox%
|
||||
\else\unvbox\@Exercisebox\fi\fi}
|
||||
\def\@DelayExerciseBox{\if@ShipThisExercise\if@ExerciseDelay%
|
||||
\global\setbox\temp@Exercisebox%
|
||||
\vbox{\unvbox\all@Exercisebox\vskip\Exesep\unvbox\@Exercisebox\vskip\z@}%
|
||||
\global\setbox\all@Exercisebox\copy\temp@Exercisebox%
|
||||
\else\vskip\Exesep\unvbox\@Exercisebox\fi\fi}
|
||||
\newcommand{\shipoutAnswer}{\if@AnswerOutput\unvbox\all@Answerbox\fi}
|
||||
\newcommand{\shipoutExercise}{\if@ExerciseOutput\unvbox\all@Exercisebox\fi}
|
||||
\def\beginExerciseEnv{\@InitExe\@ifnextchar[\@@ExeEnv{\@@ExeEnv[]}}%]
|
||||
\def\@@ExeEnv[#1]{\setkeys{PPExercise}{#1}%
|
||||
\global\@Answerfalse\@BeginExeBox\@@@ExeEnv}
|
||||
\newcommand{\@@@ExeEnv}{%
|
||||
\@selectExercise{\ExerciseTrueLabel}
|
||||
\@QuestionLevel1
|
||||
\refstepExecounter
|
||||
\begingroup\@getExerciseInfo\ExerciseHeader\endgroup}
|
||||
\def\endExerciseEnv{\termineliste{1}\@EndExeBox}
|
||||
\def\ExerciseCmd{\@InitExe\@ifstar{\global\@ExeStaredtrue\@ExeCmd}%
|
||||
{\global\@ExeStaredfalse\@ExeCmd}}
|
||||
\def\@ExeCmd{\@ifnextchar[\@@ExeCmd{\@@ExeCmd[]}}%] for emacs
|
||||
\def\@@ExeCmd[#1]{\setkeys{PPExercise}{#1}\@@@ExeCmd}
|
||||
\newcommand{\@@@ExeCmd}{%
|
||||
\ifnum\@QuestionLevel=0
|
||||
\advance \@QuestionLevel by 1
|
||||
\begin{list}{\@getExerciseInfo\ExerciseListHeader}%
|
||||
{\partopsep\Exepartopsep \labelsep\Exelabelsep \itemsep \Exesep%
|
||||
\parsep\Exeparsep \topsep\Exetopsep \labelwidth\Exelabelwidth%
|
||||
\leftmargin\Exeleftmargin \rightmargin\Exerightmargin}
|
||||
\else
|
||||
\termineliste{1}\@EndExeBox
|
||||
\fi
|
||||
\@selectExercise{\ExerciseTrueLabel}
|
||||
\global\@Answerfalse\@BeginExeBox\refstepExecounter%
|
||||
\item\ignorespaces
|
||||
}
|
||||
\def\defineExePartInEnv{\def\@ExePartHeader{\ExePartHeader}}
|
||||
\def\defineExePartInList{\def\@ExePartHeader{\ExePartListHeader}}
|
||||
\def\defineExerciseEnv{%
|
||||
\defineExePartInEnv
|
||||
\renewenvironment{Exercise}{\global\beginExerciseEnv}%
|
||||
{\@ExeStaredfalse\endExerciseEnv}
|
||||
\renewenvironment{Exercise*}{\global\@ExeStaredtrue\beginExerciseEnv}%
|
||||
{\@ExeStaredfalse\endExerciseEnv}
|
||||
}
|
||||
\newenvironment{Exercise}{}{}
|
||||
\newenvironment{Exercise*}{}{}
|
||||
\def\defineExerciseCmd{\def\Exercise{\ExerciseCmd}}
|
||||
\renewcommand{\Exercise}{}
|
||||
\defineExerciseEnv
|
||||
\def\beginExerciseListEnv{\defineExerciseCmd\defineAnswerCmd%
|
||||
\defineExePartInList}
|
||||
\def\endExerciseListEnv{\termineliste{1}\@EndExeBox\termineliste{0}%
|
||||
\defineExerciseEnv\defineAnswerEnv}
|
||||
\newenvironment{ExerciseList}{\beginExerciseListEnv}{\endExerciseListEnv}
|
||||
\def\QuestionTitle{}
|
||||
\newif\if@QuestionTitle \@QuestionTitlefalse
|
||||
\global\newcount\QuestionDifficulty \QuestionDifficulty=0
|
||||
\newif\if@QuestionDifficulty \@QuestionDifficultyfalse
|
||||
\define@key{PPQuestion}{title}{%
|
||||
\global\@QuestionTitletrue\gdef\QuestionTitle{\string#1}}
|
||||
\define@key{PPQuestion}{difficulty}{%
|
||||
\global\@QuestionDifficultytrue\global\QuestionDifficulty=\number#1}
|
||||
\def\@InitQuestion{\gdef\QuestionTitle{}%
|
||||
\global\QuestionDifficulty=0%
|
||||
\global\@QuestionTitlefalse%
|
||||
\global\@QuestionDifficultyfalse}
|
||||
\def\@getQuestionInfo{%
|
||||
\if@QuestionTitle\else\def\QuestionHeaderTitle{}\fi
|
||||
\if@QuestionDifficulty\else\def\QuestionHeaderDifficulty{}\fi
|
||||
}
|
||||
\def\EndCurrentQuestion{\termineliste{1}}
|
||||
\def\Question{\@InitQuestion\@ifnextchar[\@@Question{\@@Question[]}}%]
|
||||
\def\@@Question[#1]{\setkeys{PPQuestion}{#1}\@@@Question}
|
||||
\def\@QuestionHeader{\item[{\makebox[0cm][r]{\begingroup\@getQuestionInfo%
|
||||
\QuestionHeaderDifficulty\QuestionNB\endgroup}}]%
|
||||
\begingroup\@getQuestionInfo\QuestionHeaderTitle\endgroup\ignorespaces}
|
||||
\newcommand{\@@@Question}{%
|
||||
\ifnum\@QuestionLevel=1
|
||||
\advance \@QuestionLevel by 1
|
||||
\begin{list}{}{\leftmargin \QuestionIndent
|
||||
\partopsep0pt \parsep\parskip \topsep \QuestionBefore
|
||||
\itemsep \QuestionBefore \labelwidth 2em
|
||||
\labelsep .5em
|
||||
\usecounter{Question}}
|
||||
\if@echapq
|
||||
\setcounter{Question}{\value{savedQuestion}}\global\@echapqfalse
|
||||
\fi
|
||||
\refstepcounter{Question}
|
||||
\@restoremathindent
|
||||
\@decalemathindent{\QuestionIndent}
|
||||
\@QuestionHeader
|
||||
\else
|
||||
\ifnum\@QuestionLevel=2
|
||||
\refstepcounter{Question}
|
||||
\@QuestionHeader
|
||||
\else
|
||||
\ifnum\@QuestionLevel>2
|
||||
\termineliste{2}
|
||||
\refstepcounter{Question}
|
||||
\@QuestionHeader
|
||||
\else
|
||||
\PackageError{exercise}{You don't respect the hierarchy of
|
||||
questions}{Verify the Question}
|
||||
\fi
|
||||
\fi
|
||||
\fi
|
||||
}
|
||||
\def\subQuestionTitle{}
|
||||
\newif\if@subQuestionTitle\@subQuestionTitlefalse
|
||||
\global\newcount\subQuestionDifficulty\subQuestionDifficulty=0
|
||||
\newif\if@subQuestionDifficulty\@subQuestionDifficultyfalse
|
||||
\define@key{PPsubQuestion}{title}{%
|
||||
\gdef\subQuestionTitle{\string#1}\global\@subQuestionTitletrue}
|
||||
\define@key{PPsubQuestion}{difficulty}{%
|
||||
\global\@subQuestionDifficultytrue\global\subQuestionDifficulty=\number#1}
|
||||
\def\@InitsubQuestion{\gdef\subQuestionTitle{}%
|
||||
\global\subQuestionDifficulty=0%
|
||||
\global\@subQuestionTitlefalse%
|
||||
\global\@subQuestionDifficultyfalse}
|
||||
\def\@getsubQuestionInfo{%
|
||||
\if@subQuestionTitle\else\def\subQuestionHeaderTitle{}\fi
|
||||
\if@subQuestionDifficulty\else\def\subQuestionHeaderDifficulty{}\fi
|
||||
}
|
||||
\def\EndCurrentsubQuestion{\termineliste{2}}
|
||||
\def\subQuestion{\@InitsubQuestion%
|
||||
\@ifnextchar[\@@subQuestion{\@@subQuestion[]}}%]
|
||||
\def\@@subQuestion[#1]{\setkeys{PPsubQuestion}{#1}\@@@subQuestion}
|
||||
\def\@subQuestionHeader{\item[{\makebox[0cm][r]%
|
||||
{\begingroup\@getsubQuestionInfo\subQuestionHeaderDifficulty%
|
||||
\subQuestionNB\endgroup}}]%
|
||||
\begingroup\@getsubQuestionInfo\subQuestionHeaderTitle\endgroup%
|
||||
\ignorespaces}
|
||||
\newcommand{\@@@subQuestion}{%
|
||||
\ifnum\@QuestionLevel=2
|
||||
\advance \@QuestionLevel by 1
|
||||
\begin{list}{}{\leftmargin \subQuestionIndent
|
||||
\partopsep0pt \parsep\parskip \topsep \subQuestionBefore
|
||||
\itemsep \subQuestionBefore \labelwidth 2em
|
||||
\labelsep .5em
|
||||
\usecounter{subQuestion}}
|
||||
\if@echapq
|
||||
\setcounter{subQuestion}{\value{savedsubQuestion}}%
|
||||
\global\@echapqfalse
|
||||
\fi
|
||||
\refstepcounter{subQuestion}
|
||||
\@restoremathindent
|
||||
\@decalemathindent{\subQuestionIndent}
|
||||
\@subQuestionHeader
|
||||
\else
|
||||
\ifnum\@QuestionLevel=3
|
||||
\refstepcounter{subQuestion}
|
||||
\@subQuestionHeader
|
||||
\else
|
||||
\ifnum\@QuestionLevel>3
|
||||
\termineliste{3}
|
||||
\refstepcounter{subQuestion}
|
||||
\@subQuestionHeader
|
||||
\else
|
||||
\PackageError{exercise}{You don't respect the hierarchy of
|
||||
subQuestion}{Verify the subQuestion}
|
||||
\fi
|
||||
\fi
|
||||
\fi
|
||||
}
|
||||
\def\subsubQuestionTitle{}
|
||||
\newif\if@subsubQuestionTitle\@subsubQuestionTitlefalse
|
||||
\global\newcount\subsubQuestionDifficulty\subsubQuestionDifficulty=0
|
||||
\newif\if@subsubQuestionDifficulty\@subsubQuestionDifficultyfalse
|
||||
\define@key{PPsubsubQuestion}{title}{%
|
||||
\gdef\subsubQuestionTitle{\string#1}\global\@subsubQuestionTitletrue}
|
||||
\define@key{PPsubsubQuestion}{difficulty}{%
|
||||
\global\@subsubQuestionDifficultytrue%
|
||||
\global\subsubQuestionDifficulty=\number#1}
|
||||
\def\@InitsubsubQuestion{\gdef\subsubQuestionTitle{}%
|
||||
\global\subsubQuestionDifficulty=0%
|
||||
\global\@subsubQuestionTitlefalse%
|
||||
\global\@subsubQuestionDifficultyfalse}
|
||||
\def\@getsubsubQuestionInfo{%
|
||||
\if@subsubQuestionTitle\else\def\subsubQuestionHeaderTitle{}\fi
|
||||
\if@subsubQuestionDifficulty\else\def\subsubQuestionHeaderDifficulty{}\fi
|
||||
}
|
||||
\def\EndCurrentsubsubQuestion{\termineliste{3}}
|
||||
\def\subsubQuestion{\@InitsubsubQuestion%
|
||||
\@ifnextchar[\@@subsubQuestion{\@@subsubQuestion[]}}%]
|
||||
\def\@@subsubQuestion[#1]{\setkeys{PPsubsubQuestion}{#1}\@@@subsubQuestion}
|
||||
\def\@subsubQuestionHeader{\item[{\makebox[0cm][r]%
|
||||
{\begingroup\@getsubsubQuestionInfo\subsubQuestionHeaderDifficulty%
|
||||
\subsubQuestionNB\endgroup}}]%
|
||||
\begingroup\@getsubsubQuestionInfo\subsubQuestionHeaderTitle\endgroup%
|
||||
\ignorespaces}
|
||||
\newcommand{\@@@subsubQuestion}{%
|
||||
\ifnum\@QuestionLevel=3
|
||||
\advance \@QuestionLevel by 1
|
||||
\begin{list}{}{\leftmargin \subsubQuestionIndent
|
||||
\partopsep0pt \parsep\parskip \topsep \subsubQuestionBefore
|
||||
\itemsep \subsubQuestionBefore \labelwidth 2em
|
||||
\labelsep .5em
|
||||
\usecounter{subsubQuestion}}
|
||||
\if@echapq
|
||||
\setcounter{subsubQuestion}{\value{savedsubsubQuestion}}%
|
||||
\global\@echapqfalse
|
||||
\fi
|
||||
\refstepcounter{subsubQuestion}
|
||||
\@restoremathindent
|
||||
\@decalemathindent{\subsubQuestionIndent}
|
||||
\@subsubQuestionHeader
|
||||
\else
|
||||
\ifnum\@QuestionLevel=4
|
||||
\refstepcounter{subsubQuestion}
|
||||
\@subsubQuestionHeader
|
||||
\else
|
||||
\ifnum\@QuestionLevel>4
|
||||
\termineliste{4}
|
||||
\refstepcounter{subsubQuestion}
|
||||
\@subsubQuestionHeader
|
||||
\else
|
||||
\PackageError{exercise}{You don't respect the hierarchy of
|
||||
subsubQuestion}{Verify the subsubQuestion}
|
||||
\fi
|
||||
\fi
|
||||
\fi
|
||||
}
|
||||
\newif\if@ExePartStared \@ExePartStaredfalse
|
||||
\newif\if@ExePartTitle \@ExePartTitlefalse
|
||||
\newif\if@ExePartReName \@ExePartReNamefalse
|
||||
\newif\if@ExePartDifficulty \@ExePartDifficultyfalse
|
||||
\global\newcount\ExePartDifficulty \ExePartDifficulty=0
|
||||
\def\theExePartDifficulty{\marker{\DifficultyMarker}{\ExePartDifficulty}}
|
||||
\def\@InitExePart{\global\@echapqfalse%
|
||||
\gdef\ExePartTitle{}%
|
||||
\gdef\@ExePartName{}%
|
||||
\global\ExePartDifficulty=0%
|
||||
\global\@ExePartTitlefalse%
|
||||
\global\@ExePartReNamefalse%
|
||||
\global\@ExePartDifficultyfalse%
|
||||
\setcounter{Question}{0}\termineliste{1}}
|
||||
\define@key{PPExePart}{title}{\gdef\ExePartTitle{\string#1}%
|
||||
\global\@ExePartTitletrue}
|
||||
\define@key{PPExePart}{name}{\gdef\@ExePartName{\string#1}%
|
||||
\global\@ExePartReNametrue}
|
||||
\define@key{PPExePart}{difficulty}{\global\@ExePartDifficultytrue%
|
||||
\global\ExePartDifficulty=\number#1}
|
||||
\def\@getExePartInfo{%
|
||||
\if@ExePartReName\def\ExePartName{\@ExePartName}\fi
|
||||
\if@ExePartTitle\else\def\ExePartHeaderTitle{}\fi
|
||||
\if@ExePartDifficulty\else\def\ExePartHeaderDifficulty{}\fi
|
||||
\if@ExePartStared\def\ExePartHeaderNB{}\fi
|
||||
}
|
||||
\def\ExePart{\@InitExePart\@ifstar{\global\@ExePartStaredtrue\@ExePart}%
|
||||
{\global\@ExePartStaredfalse\@ExePart}}
|
||||
\def\@ExePart{\@ifnextchar[\@@ExePart{\@@ExePart[]}}%] for emacs
|
||||
\def\@@ExePart[#1]{\setkeys{PPExePart}{#1}\@@@ExePart}
|
||||
\newcommand{\@@@ExePart}{%
|
||||
\if@ExePartStared\else\refstepcounter{ExePart}\fi
|
||||
\begingroup\@getExePartInfo\@ExePartHeader\endgroup}
|
||||
\newbox\@Answerbox
|
||||
%% \newcommand{\AnswerHeaderRef}{Answer of \ExerciseName\ \theExercise}
|
||||
%% \newcommand{\AnswerListHeaderRef}{Answer (ex.\ \theExercise)\ ---\ }
|
||||
\newcommand{\AnswerHeader}{\medskip\centerline{\textbf{Answer of
|
||||
\ExerciseName \ExerciseHeaderNB}\smallskip}}
|
||||
\newcommand{\AnswerListHeader}{\textbf{Answer (ex.\
|
||||
\ExerciseHeaderNB)\ ---\ }}
|
||||
\def\@InitAnswer{\@savemathindent\global\@echapqfalse%
|
||||
\gdef\AnswerRef{}%
|
||||
\global\@AnswerReffalse%
|
||||
\gdef\AnswerNB{}%
|
||||
\global\@AnswerNBfalse%
|
||||
\setcounter{ExePart}{0}%
|
||||
\setcounter{Question}{0}}
|
||||
\def\@getAnswerInfo{%
|
||||
\if@AnswerRef%
|
||||
\def\AnswerHeader{\ref{PP\AnswerRef}}%
|
||||
\def\AnswerListHeader{\ref{PP\AnswerRef}}%
|
||||
\else
|
||||
\if@AnswerNB
|
||||
\def\ExerciseTitle{}
|
||||
\def\ExerciseName{}
|
||||
\def\ExerciseOrigin{}
|
||||
\ExerciseDifficulty=0
|
||||
\def\theExercise{\AnswerNB}
|
||||
\else
|
||||
\if@AswLastExe
|
||||
\else
|
||||
\PackageWarning{Exercise}%
|
||||
{A answer has no reference and no number}{}%
|
||||
\def\AnswerHeaderRef{\AnswerName\ ???}%
|
||||
\def\AnswerListHeaderRef{\AnswerName\ ???}%
|
||||
\fi\fi\fi}
|
||||
\newif\if@AnswerRef \@AnswerReffalse
|
||||
\newif\if@AnswerNB \@AnswerNBfalse
|
||||
\define@key{PPAnswer}{ref}{\global\@AnswerReftrue\gdef\AnswerRef{\string#1}}
|
||||
\define@key{PPAnswer}{number}{\global\@AnswerNBtrue\gdef\AnswerNB{\string#1}}
|
||||
\def\beginAnswerEnv{\@InitAnswer\@ifnextchar[\@@AnswerEnv{\@@AnswerEnv[]}}%]
|
||||
\def\@@AnswerEnv[#1]{\setkeys{PPAnswer}{#1}%
|
||||
\global\@Answertrue\@BeginExeBox\@@@AnswerEnv}
|
||||
\newcommand{\@@@AnswerEnv}{%
|
||||
\@QuestionLevel1
|
||||
\begingroup\@getExerciseInfo\@getAnswerInfo\AnswerHeader\endgroup}
|
||||
\def\endAnswerEnv{\termineliste{1}\@EndExeBox}
|
||||
\newenvironment{Answer}{}{}
|
||||
\def\defineAnswerEnv{
|
||||
\gdef\@AnswerHeaderRef{\AnswerHeader}
|
||||
\renewenvironment{Answer}{\beginAnswerEnv}{\endAnswerEnv}}
|
||||
\defineAnswerEnv
|
||||
\def\AnswerCmd{\@InitAnswer\@ifnextchar[\@@AnswerCmd{\@@AnswerCmd[]}}
|
||||
\def\@@AnswerCmd[#1]{\setkeys{PPAnswer}{#1}\@@@AnswerCmd}
|
||||
\newcommand{\@@@AnswerCmd}{%
|
||||
\ifnum\@QuestionLevel=0
|
||||
\advance \@QuestionLevel by 1
|
||||
\begin{list}{}{\partopsep\Exepartopsep \labelsep\Exelabelsep
|
||||
\itemsep \Exesep \parsep\Exeparsep
|
||||
\topsep\Exetopsep \labelwidth\Exelabelwidth
|
||||
\leftmargin\Exeleftmargin
|
||||
\rightmargin\Exerightmargin }
|
||||
\refstepExecounter
|
||||
\else
|
||||
\termineliste{1}\@EndExeBox
|
||||
\fi
|
||||
\global\@Answertrue\@BeginExeBox%
|
||||
\item[\bgroup\@getAnswerInfo\AnswerListHeader\egroup]\ignorespaces
|
||||
}
|
||||
\def\defineAnswerCmd{\gdef\@AnswerHeaderRef{\AnswerListHeader}%
|
||||
\gdef\Answer{\AnswerCmd}}
|
||||
\newif\if@ExerciseSelected\@ExerciseSelectedfalse
|
||||
\newif\if@ExerciseNoLabelSelected\@ExerciseNoLabelSelectedtrue
|
||||
\newif\if@ExerciseOmitted\@ExerciseOmittedfalse
|
||||
\newif\if@ShipThisExercise\@ShipThisExercisetrue
|
||||
\newcommand{\ExerciseStartSelectNoLabel}{\@ExerciseNoLabelSelectedtrue}
|
||||
\newcommand{\ExerciseStopSelectNoLabel}{\@ExerciseNoLabelSelectedfalse}
|
||||
\newcommand{\ExerciseStopSelect}{\@ExerciseSelectedfalse}
|
||||
\newcommand{\ExerciseStartSelect}{\@ExerciseSelectedtrue\@ifstar{\@ExerciseOmittedtrue\def@ListOfExercise}{\@ExerciseOmittedfalse\def@ListOfExercise}}
|
||||
\def\def@ListOfExercise#1{\gdef\@ListOfExercise{#1}}
|
||||
\def\@selectExercise#1{%
|
||||
\ifx#1\@empty
|
||||
\if@ExerciseNoLabelSelected
|
||||
\global\@ShipThisExercisetrue
|
||||
\else
|
||||
\global\@ShipThisExercisefalse
|
||||
\fi
|
||||
\else
|
||||
\if@ExerciseSelected
|
||||
\global\@ShipThisExercisefalse
|
||||
\@for\@label:=\@ListOfExercise\do
|
||||
{ \ifthenelse{\equal{\@label}{#1}}{
|
||||
\message{[\@label = #1] OK !!!}
|
||||
\global\@ShipThisExercisetrue
|
||||
}{}
|
||||
}
|
||||
\if@ExerciseOmitted
|
||||
\if@ShipThisExercise
|
||||
\global\@ShipThisExercisefalse
|
||||
\else
|
||||
\global\@ShipThisExercisetrue
|
||||
\fi
|
||||
\fi
|
||||
\fi
|
||||
\fi
|
||||
}
|
||||
\newcommand{\ExeText}{\setcounter{savedQuestion}{\value{Question}}%
|
||||
\termineliste{1}\@echapqtrue}
|
||||
\newcount\colonnesLevel \colonnesLevel=-10
|
||||
\newskip\tempskipa
|
||||
\newskip\tempskipb
|
||||
\def\deuxcolonnes{\tempskipa=\multicolsep\colonnesLevel=\@QuestionLevel
|
||||
\ifcase\@QuestionLevel \multicolsep=\QuestionBefore %
|
||||
\or
|
||||
\multicolsep=\subQuestionBefore\or\multicolsep=\subsubQuestionBefore\fi%
|
||||
\begin{multicols}{2}}
|
||||
\@ifundefined{if@fleqn}{\newif\if@fleqn\@fleqnfalse}{}
|
||||
\newlength{\@savedmathindent}
|
||||
\newcommand{\@savemathindent}{\relax}
|
||||
\newcommand{\@decalemathindent}[1]{\relax}
|
||||
\newcommand{\@restoremathindent}{\relax}
|
||||
\if@fleqn %
|
||||
\renewcommand{\@savemathindent}{\setlength{\@savedmathindent}{\mathindent}}
|
||||
\renewcommand{\@decalemathindent}[1]{\addtolength{\mathindent}{#1}}
|
||||
\renewcommand{\@restoremathindent}{\setlength{\mathindent}{\@savedmathindent}}
|
||||
\else
|
||||
\renewcommand{\@savemathindent}{\relax}
|
||||
\renewcommand{\@decalemathindent}[1]{\relax}
|
||||
\renewcommand{\@restoremathindent}{\relax}
|
||||
\fi
|
||||
\def\renewcounter#1{%
|
||||
\@ifundefined{c@#1}
|
||||
{\@latex@error{counter #1 undefined}\@ehc}%
|
||||
\relax
|
||||
\let\@ifdefinable\@rc@ifdefinable
|
||||
\@ifnextchar[{\@newctr{#1}}{}}
|
||||
\endinput
|
||||
%%
|
||||
%% End of file `exercise.sty'.
|
BIN
docs/ProgrammingCryptol/utils/galois.jpg
Normal file
BIN
docs/ProgrammingCryptol/utils/galois.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
979
docs/ProgrammingCryptol/utils/glossary.sty
Normal file
979
docs/ProgrammingCryptol/utils/glossary.sty
Normal file
@ -0,0 +1,979 @@
|
||||
%%
|
||||
%% This is file `glossary.sty',
|
||||
%% generated with the docstrip utility.
|
||||
%%
|
||||
%% The original source files were:
|
||||
%%
|
||||
%% glossary.dtx (with options: `glossary.sty,package')
|
||||
%% Copyright (C) 2006 Nicola Talbot, all rights reserved.
|
||||
%% If you modify this file, you must change its name first.
|
||||
%% You are NOT ALLOWED to distribute this file alone. You are NOT
|
||||
%% ALLOWED to take money for the distribution or use of either this
|
||||
%% file or a changed version, except for a nominal charge for copying
|
||||
%% etc.
|
||||
%% \CharacterTable
|
||||
%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
|
||||
%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
|
||||
%% Digits \0\1\2\3\4\5\6\7\8\9
|
||||
%% Exclamation \! Double quote \" Hash (number) \#
|
||||
%% Dollar \$ Percent \% Ampersand \&
|
||||
%% Acute accent \' Left paren \( Right paren \)
|
||||
%% Asterisk \* Plus \+ Comma \,
|
||||
%% Minus \- Point \. Solidus \/
|
||||
%% Colon \: Semicolon \; Less than \<
|
||||
%% Equals \= Greater than \> Question mark \?
|
||||
%% Commercial at \@ Left bracket \[ Backslash \\
|
||||
%% Right bracket \] Circumflex \^ Underscore \_
|
||||
%% Grave accent \` Left brace \{ Vertical bar \|
|
||||
%% Right brace \} Tilde \~}
|
||||
\NeedsTeXFormat{LaTeX2e}
|
||||
\ProvidesPackage{glossary}[2006/07/20 2.4 (NLCT)]
|
||||
\RequirePackage{ifthen}
|
||||
\RequirePackage{keyval}
|
||||
\define@key{gloss}
|
||||
{style}
|
||||
{\ifthenelse{\equal{#1}{list} \or \equal{#1}{altlist}
|
||||
\or \equal{#1}{super} \or \equal{#1}{long}}
|
||||
{\def\gls@style{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary style '#1'}
|
||||
{Available styles are: list, altlist, super and long}}}
|
||||
\define@key{gloss}
|
||||
{header}[plain]{\ifthenelse{\equal{#1}{none} \or \equal{#1}{plain}}
|
||||
{\def\gls@header{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary style '#1'}
|
||||
{Available styles are: none and plain}}}
|
||||
\define@key{gloss}
|
||||
{border}[plain]{\ifthenelse{\equal{#1}{none} \or \equal{#1}{plain}}
|
||||
{\def\gls@border{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary border '#1'}
|
||||
{Available styles are: none and plain}}}
|
||||
\newcount\gls@cols
|
||||
\define@key{gloss}{cols}{\gls@cols=#1\relax
|
||||
\ifthenelse{\gls@cols<2 \or \gls@cols>3}
|
||||
{\PackageError{glossary}
|
||||
{invalid number of columns}
|
||||
{The cols option can only be 2 or 3}}
|
||||
{}}
|
||||
\define@key{gloss}
|
||||
{number}
|
||||
{\ifthenelse{\equal{#1}{none}}
|
||||
{\def\gls@glossary@number{#1}}
|
||||
{\@ifundefined{c@#1}{
|
||||
\PackageError{glossary}
|
||||
{Unknown glossary number style '#1'}
|
||||
{You may either specify "none" or the name of a counter,
|
||||
e.g. "section"}\def\gls@glossary@number{page}}{\def\gls@glossary@number{#1}}}}
|
||||
\newif\ifgls@toc
|
||||
\define@key{gloss}{toc}[true]{\ifthenelse{\equal{#1}{true}
|
||||
\or \equal{#1}{false}}
|
||||
{\csname gls@toc#1\endcsname}
|
||||
{\PackageError{glossary}{Glossary option 'toc' is boolean}
|
||||
{The value of 'toc' can only be set to 'true' or 'false'}}}
|
||||
\newif\ifgls@hypertoc
|
||||
\define@key{gloss}{hypertoc}[true]{%
|
||||
\ifthenelse{\equal{#1}{true} \or \equal{#1}{false}}
|
||||
{\csname gls@hypertoc#1\endcsname}
|
||||
{\PackageError{glossary}{Glossary option 'hypertoc' is boolean}
|
||||
{The value of 'hypertoc' can only be set to 'true' or 'false'}}}
|
||||
\newif\ifgls@section
|
||||
\define@key{gloss}{section}[true]{%
|
||||
\ifthenelse{\equal{#1}{true} \or \equal{#1}{false}}
|
||||
{\csname gls@section#1\endcsname}
|
||||
{\PackageError{glossary}{Glossary option 'section' is boolean}
|
||||
{The value of 'section' can only be set to 'true' or 'false'}}}
|
||||
\gls@sectionfalse
|
||||
\newif\ifglshyper
|
||||
\newif\ifglshyperacronym
|
||||
\define@key{gloss}{hyper}[true]{%
|
||||
\ifthenelse{\equal{#1}{true} \or \equal{#1}{false}}
|
||||
{\csname glshyper#1\endcsname\glshyperacronymtrue}
|
||||
{\PackageError{glossary}{Glossary option 'hyper' is boolean}
|
||||
{The value of 'hyper' can only be set to 'true' or 'false'}}}
|
||||
\define@key{gloss}{hyperacronym}[true]{%
|
||||
\ifthenelse{\equal{#1}{true} \or \equal{#1}{false}}
|
||||
{\csname glshyperacronym#1\endcsname}
|
||||
{\PackageError{glossary}{Glossary option 'hyperacronym' is boolean}
|
||||
{The value of 'hyperacronym' can only be set to 'true' or 'false'}}}
|
||||
\newif\ifglsacronym
|
||||
\define@key{gloss}{acronym}[true]{%
|
||||
\ifthenelse{\equal{#1}{true} \or \equal{#1}{false}}
|
||||
{\setboolean{glsacronym}{#1}}{%
|
||||
\PackageError{glossary}{Glossary option 'acronym' is boolean}{The
|
||||
value of 'acronym' can only be set to 'true' or 'false'}}}
|
||||
\newif\ifglsglobal
|
||||
\define@key{gloss}{global}[true]{\ifthenelse{\equal{#1}{true}\or
|
||||
\equal{#1}{false}}{\setboolean{glsglobal}{#1}}{%
|
||||
\PackageError{glossary}{Glossary option 'global' is boolean}{The
|
||||
value of 'global' can only be set to 'true' or 'false'}}}
|
||||
\def\gls@style{long}
|
||||
\def\gls@header{none}
|
||||
\def\gls@border{none}
|
||||
\def\gls@glossary@number{page}
|
||||
\gls@cols=2\relax
|
||||
\gls@tocfalse
|
||||
\@ifundefined{hyperpage}{\glshyperfalse\glshyperacronymfalse}{%
|
||||
\glshypertrue\glshyperacronymtrue}
|
||||
\@ifundefined{hypertarget}{
|
||||
\newcommand{\glosslabel}[2]{#2}%
|
||||
\newcommand{\glossref}[2]{#2}%
|
||||
}{%
|
||||
\newcommand{\glosslabel}[2]{\hypertarget{#1}{#2}}%
|
||||
\newcommand{\glossref}[2]{\hyperlink{#1}{#2}}
|
||||
}
|
||||
\@ifundefined{xspace}{%
|
||||
\let\glsxspace\relax}{%
|
||||
\let\glsxspace\xspace}
|
||||
\let\glossaryalignment\relax
|
||||
\newcommand{\glossarypackageoptions}[1]{\setkeys{gloss}{#1}}
|
||||
\InputIfFileExists{glossary.cfg}{%
|
||||
\typeout{Glossary configuration file loaded}}{%
|
||||
\typeout{No configuration file glossary.cfg found}}
|
||||
\renewcommand{\glossarypackageoptions}[1]{%
|
||||
\PackageError{glossary}{Command \string\glossarypackageoptions
|
||||
^^Jcan only be used in configuration file}{}}
|
||||
\DeclareOption*{\edef\@pkg@ptions{\noexpand
|
||||
\setkeys{gloss}{\CurrentOption}}
|
||||
\ifthenelse{\equal{\CurrentOption}{}}{}{\@pkg@ptions}}
|
||||
\ProcessOptions
|
||||
\ifthenelse{\(\equal{\gls@style}{list} \or
|
||||
\equal{\gls@style}{altlist}\) \and
|
||||
\(\not\equal{\gls@header}{none} \or \not\equal{\gls@border}{none}
|
||||
\or \gls@cols=3\)}
|
||||
{\PackageError{glossary}{You can't have option 'style=list' or
|
||||
'style=altlist' in combination with any of the other style
|
||||
options}{The 'list' and 'altlist' options don't have a header,
|
||||
border or number of columns option.}}
|
||||
{}
|
||||
\ifthenelse{\boolean{gls@hypertoc} \and \boolean{gls@toc}}{%
|
||||
\PackageWarning{glossary}{Can't have both 'toc' and
|
||||
'hypertoc', ignoring 'toc' option}
|
||||
\ifgls@hypertoc\gls@tocfalse\fi}{}
|
||||
\define@key{wrgloss}{name}{%
|
||||
\def\@glo@n@me{#1}%
|
||||
\@onelevel@sanitize\@glo@n@me%
|
||||
\global\let\@glo@n@me\@glo@n@me}
|
||||
\define@key{wrgloss}{description}{%
|
||||
\def\@descr{#1}%
|
||||
\@onelevel@sanitize\@descr}
|
||||
\define@key{wrgloss}{sort}{%
|
||||
\def\@s@rt{#1}%
|
||||
\@onelevel@sanitize\@s@rt
|
||||
\global\let\@s@rt\@s@rt}
|
||||
\define@key{wrgloss}{format}{\def\@f@rm@t{#1}}
|
||||
\define@key{wrgloss}{number}{\def\@glo@num{#1}}
|
||||
\newcommand{\@@wrglossary}{}
|
||||
\newcommand{\@glo@l@bel}{}
|
||||
\newcommand{\@gls@glossary@type}{glo}
|
||||
\renewcommand{\@wrglossary}[2][glossary]{\relax
|
||||
\gdef\@glo@n@me{}\def\@descr{}\def\@s@rt{}\def\@f@rm@t{}%
|
||||
\edef\@glo@num{\csname gls@#1@number\endcsname}\relax
|
||||
\xdef\@pr@fix{\csname @gls@#1@type\endcsname}%
|
||||
\setkeys{wrgloss}{#2}\relax
|
||||
\ifthenelse{\equal{\@glo@num}{none}}{\def\@@glo@num{\thepage}}{%
|
||||
\@ifundefined{c@\@glo@num}{\PackageError{glossary}{%
|
||||
Not such counter '\@glo@num'}{The value of the 'number' key
|
||||
must be the name of a counter or the word "none"}%
|
||||
\def\@@glo@num{\thepage}}{%
|
||||
\edef\@@glo@num{\csname the\@glo@num\endcsname}}}%
|
||||
\ifthenelse{\equal{\@s@rt}{}}{\gdef\@s@rt{\@glo@n@me}}{}%
|
||||
\ifthenelse{\equal{\@glo@l@bel}{}}{%
|
||||
\gdef\@glo@l@bel{\@pr@fix:\@s@rt}}{}%
|
||||
\ifthenelse{\equal{\@f@rm@t}{}}
|
||||
{\expandafter\protected@write\csname @#1file\endcsname{}%
|
||||
{\string\glossaryentry{\@s@rt @{%
|
||||
\string\glosslabel{\@glo@l@bel}{\@glo@n@me}}\@descr
|
||||
\string\relax|glsnumformat}{\@@glo@num}}}
|
||||
{\ifthenelse{\equal{\@f@rm@t}{hyperrm} \or
|
||||
\equal{\@f@rm@t}{hypersf} \or \equal{\@f@rm@t}{hypertt}
|
||||
\or \equal{\@f@rm@t}{hypermd} \or \equal{\@f@rm@t}{hyperbf}
|
||||
\or \equal{\@f@rm@t}{hyperit} \or \equal{\@f@rm@t}{hyperem}
|
||||
\or \equal{\@f@rm@t}{hypersl} \or \equal{\@f@rm@t}{hyperup}
|
||||
\or \equal{\@f@rm@t}{hypersc}}
|
||||
{\expandafter\protected@write\csname @#1file\endcsname{}%
|
||||
{\string\glossaryentry{\@s@rt @{%
|
||||
\string\glosslabel{\@glo@l@bel}{\@glo@n@me}}\@descr
|
||||
\string\relax|\@f@rm@t[\@glo@num]}{\@@glo@num}}}
|
||||
{\expandafter\protected@write\csname @#1file\endcsname{}%
|
||||
{\string\glossaryentry{\@s@rt @{%
|
||||
\string\glosslabel{\@glo@l@bel}{\@glo@n@me}}\@descr
|
||||
\string\relax|\@f@rm@t}{\@@glo@num}}}}\relax
|
||||
\endgroup\@esphack
|
||||
\@@wrglossary
|
||||
}
|
||||
\define@key{wrnsgloss}{name}{\def\@glo@n@me{#1}}
|
||||
\define@key{wrnsgloss}{description}{\def\@descr{#1}}
|
||||
\define@key{wrnsgloss}{sort}{\def\@s@rt{#1}}
|
||||
\define@key{wrnsgloss}{format}{\def\@f@rm@t{#1}}
|
||||
\define@key{wrnsgloss}{number}{\def\@glo@num{#1}}
|
||||
\newcommand{\@gls@getn@me}[1]{%
|
||||
\def\@glo@n@me{}\setkeys{wrnsgloss}{#1}%
|
||||
}
|
||||
\newcommand{\@gls@getdescr}[1]{%
|
||||
\@bsphack\begingroup
|
||||
\def\@descr{}%
|
||||
\setkeys{wrgloss}{#1}%
|
||||
\global\let\@glo@desc\@descr
|
||||
\endgroup\@esphack
|
||||
}
|
||||
\newcommand{\xglossary}{\renewcommand{\@@wrglossary}[1]{%
|
||||
\glossref{\@glo@l@bel}{##1}\renewcommand{\@@wrglossary}{}}%
|
||||
\glossary}
|
||||
\newcommand*{\@glo@label@list}{}
|
||||
\toksdef\gls@ta=0 \toksdef\gls@tb=2
|
||||
\newcommand{\@glo@label@addtolist}[1]{%
|
||||
\gls@ta={{#1}}\gls@tb=\expandafter{\@glo@label@list}%
|
||||
\xdef\@glo@label@list{\the\gls@ta,\the\gls@tb}}
|
||||
\newcommand*{\storeglosentry}[3][glossary]{%
|
||||
\ifthenelse{\equal{#2}{*}}{%
|
||||
\PackageError{glossary}{Glossary label '*' invalid}{You can't have
|
||||
a glossary entry with a * as the label}}{%
|
||||
\@ifundefined{glo@#2@entry}{%
|
||||
\@glo@label@addtolist{#2}%
|
||||
\expandafter\def\csname glo@#2@type\endcsname{#1}%
|
||||
\expandafter\def\csname glo@#2@entry\endcsname{#3}%
|
||||
\@gls@getn@me{#3}%
|
||||
\expandafter\protected@edef\csname glo@#2@name\endcsname{\@glo@n@me}%
|
||||
}{%
|
||||
\PackageError{glossary}{Glossary entry '#2' already
|
||||
defined}{There already exists a glossary entry with the label '#2'}}}%
|
||||
}
|
||||
\providecommand{\useglosentry}[2][\relax]{%
|
||||
\ifthenelse{\equal{#2}{*}}{\@for\@glolab:=\@glo@label@list\do{%
|
||||
\ifthenelse{\equal{\@glolab}{}}{}{\useglosentry[#1]{\@glolab}}}}{%
|
||||
\@ifundefined{glo@#2@type}{%
|
||||
\PackageError{glossary}{Glossary entry '#2' undefined}{You need
|
||||
to define the entry using \string\storeglosentry\space before
|
||||
using it.}}{{%
|
||||
\edef\@glostype{\csname glo@#2@type\endcsname}%
|
||||
\@glo@tb=\expandafter\expandafter\expandafter
|
||||
{\csname glo@#2@entry\endcsname}%
|
||||
\ifx#1\relax
|
||||
\edef\@glo@cmd{\expandafter\noexpand
|
||||
\csname\@glostype\endcsname{\the\@glo@tb}}%
|
||||
\else
|
||||
\edef\@glo@cmd{\expandafter\noexpand
|
||||
\csname\@glostype\endcsname{\the\@glo@tb,#1}}%
|
||||
\fi
|
||||
\@glo@cmd
|
||||
}}}}
|
||||
\providecommand{\useGlosentry}[3][\relax]{%
|
||||
\@ifundefined{glo@#2@type}{%
|
||||
\PackageError{glossary}{Glossary entry '#2' undefined}{You need
|
||||
to define the entry using \string\storeglosentry\space before
|
||||
using it.}}{{%
|
||||
\edef\@glostype{x\csname glo@#2@type\endcsname}%
|
||||
\@glo@tb=\expandafter\expandafter\expandafter
|
||||
{\csname glo@#2@entry\endcsname}%
|
||||
\ifx#1\relax
|
||||
\edef\@glo@cmd{\expandafter\noexpand
|
||||
\csname\@glostype\endcsname{\the\@glo@tb}}%
|
||||
\else
|
||||
\edef\@glo@cmd{\expandafter\noexpand
|
||||
\csname\@glostype\endcsname{\the\@glo@tb,#1}}%
|
||||
\fi
|
||||
\@glo@cmd{#3}%
|
||||
}}}
|
||||
\newcommand{\gls}[2][\relax]{%
|
||||
\useGlosentry[#1]{#2}{%
|
||||
\csname glo@#2@name\endcsname}}
|
||||
\providecommand{\saveglosentry}[3][glossary]{%
|
||||
\PackageWarning{glossary}{\string\saveglosentry\space is obsolete,
|
||||
please use \string\storeglosentry\space instead}%
|
||||
\expandafter\def\csname glo@#2@type\endcsname{#1}%
|
||||
\expandafter\def\csname glo@#2@entry\endcsname{%
|
||||
name={#2},description={#3}}}
|
||||
\newcommand*{\@gls@setnumbering}[2][glossary]{%
|
||||
\ifthenelse{\equal{#2}{none}}{%
|
||||
\def\pagecompositor{-}
|
||||
\expandafter\def\csname @#1@delimN\endcsname{}
|
||||
\expandafter\def\csname @#1@delimR\endcsname{}
|
||||
\expandafter\def\csname glsX#1Xnumformat\endcsname##1{}}{%
|
||||
\ifthenelse{\equal{#2}{page}}{%
|
||||
\def\pagecompositor{-}}{%
|
||||
\def\pagecompositor{.}}
|
||||
\expandafter\def\csname @#1@delimN\endcsname{, }
|
||||
\expandafter\def\csname @#1@delimR\endcsname{--}
|
||||
\ifglshyper
|
||||
\expandafter\def\csname glsX#1Xnumformat\endcsname##1{%
|
||||
\hyperrm[#2]{##1}}%
|
||||
\else
|
||||
\expandafter\def\csname glsX#1Xnumformat\endcsname##1{##1}\fi
|
||||
}
|
||||
}
|
||||
\@gls@setnumbering{\gls@glossary@number}
|
||||
\newcommand{\glsnumformat}[1]{%
|
||||
\@ifundefined{\@glostype}{\def\@glostype{glossary}}{}%
|
||||
\@ifundefined{glsX\@glostype Xnumformat}{%
|
||||
\PackageError{glossary}{Glossary type '\@glostype' undefined}{}}{%
|
||||
\csname glsX\@glostype Xnumformat\endcsname{#1}}}
|
||||
\def\@glostype{glossary}
|
||||
\newcommand{\delimN}{\csname @\@glostype @delimN\endcsname}
|
||||
\newcommand{\delimR}{\csname @\@glostype @delimR\endcsname}
|
||||
\newcommand{\gloitem}{\csname @\@glostype @gloitem\endcsname}
|
||||
\newcommand{\gloskip}{\csname @\@glostype @gloskip\endcsname}
|
||||
\newcommand{\delimT}{\glsafternum
|
||||
\csname @\@glostype @delimT\endcsname}
|
||||
\newcommand{\glodelim}{\csname @\@glostype @glodelim\endcsname
|
||||
\glsbeforenum}
|
||||
\newcommand{\glogroupSymbols}{}
|
||||
\newcommand{\glogroupNumbers}{}
|
||||
\newcommand{\glogroupA}{}
|
||||
\newcommand{\glogroupB}{}
|
||||
\newcommand{\glogroupC}{}
|
||||
\newcommand{\glogroupD}{}
|
||||
\newcommand{\glogroupE}{}
|
||||
\newcommand{\glogroupF}{}
|
||||
\newcommand{\glogroupG}{}
|
||||
\newcommand{\glogroupH}{}
|
||||
\newcommand{\glogroupI}{}
|
||||
\newcommand{\glogroupJ}{}
|
||||
\newcommand{\glogroupK}{}
|
||||
\newcommand{\glogroupL}{}
|
||||
\newcommand{\glogroupM}{}
|
||||
\newcommand{\glogroupN}{}
|
||||
\newcommand{\glogroupO}{}
|
||||
\newcommand{\glogroupP}{}
|
||||
\newcommand{\glogroupQ}{}
|
||||
\newcommand{\glogroupR}{}
|
||||
\newcommand{\glogroupS}{}
|
||||
\newcommand{\glogroupT}{}
|
||||
\newcommand{\glogroupU}{}
|
||||
\newcommand{\glogroupV}{}
|
||||
\newcommand{\glogroupW}{}
|
||||
\newcommand{\glogroupX}{}
|
||||
\newcommand{\glogroupY}{}
|
||||
\newcommand{\glogroupZ}{}
|
||||
\define@key{glossnum}{glsnumformat}{\def\@glsnumformat{#1}}
|
||||
\define@key{glossnum}{type}{\def\@glsnumtype{#1}}
|
||||
\define@key{glossnum}{delimN}{\def\@delimN{#1}}
|
||||
\define@key{glossnum}{delimR}{\def\@delimR{#1}}
|
||||
\define@key{glossnum}{delimT}{\def\@delimT{#1}}
|
||||
\define@key{glossnum}{gloskip}{\def\@gloskip{#1}}
|
||||
\define@key{glossnum}{glodelim}{\def\@glodelim{#1}}
|
||||
\providecommand{\ignore}[1]{}
|
||||
\newcommand{\setglossary}[1]{%
|
||||
\def\@glsnumformat{}%
|
||||
\def\@glsnumtype{glossary}%
|
||||
\def\@delimN{@dontchange@}%
|
||||
\def\@delimR{@dontchange@}%
|
||||
\def\@delimT{@dontchange@}%
|
||||
\def\@gloskip{@dontchange@}%
|
||||
\def\@glodelim{@dontchange@}%
|
||||
\setkeys{glossnum}{#1}\relax
|
||||
\@ifundefined{print\@glsnumtype}{%
|
||||
\PackageError{glossary}{Invalid glossary type '\@glsnumtype'}{%
|
||||
Glossary type '\@glsnumtype' has not been defined}
|
||||
}{%
|
||||
\ifthenelse{\equal{\@glsnumformat}{}}{}{%
|
||||
\expandafter\xdef\csname glsX\@glsnumtype Xnumformat\endcsname{%
|
||||
\noexpand\csname\@glsnumformat\noexpand\endcsname}%
|
||||
\ifthenelse{\equal{\@glsnumformat}{ignore}}{%
|
||||
\expandafter\xdef\csname @\@glsnumtype @delimN\endcsname{}%
|
||||
\expandafter\xdef\csname @\@glsnumtype @delimR\endcsname{}%
|
||||
}{}%
|
||||
}%
|
||||
\ifthenelse{\equal{\@delimN}{@dontchange@}}{}{%
|
||||
\expandafter\xdef\csname @\@glsnumtype @delimN\endcsname{%
|
||||
\@delimN}}%
|
||||
\ifthenelse{\equal{\@delimR}{@dontchange@}}{}{%
|
||||
\expandafter\xdef\csname @\@glsnumtype @delimR\endcsname{%
|
||||
\@delimR}}%
|
||||
\ifthenelse{\equal{\@delimT}{@dontchange@}}{}{%
|
||||
\expandafter\xdef\csname @\@glsnumtype @delimT\endcsname{%
|
||||
\@delimT}}%
|
||||
\ifthenelse{\equal{\@gloskip}{@dontchange@}}{}{%
|
||||
\expandafter\xdef\csname @\@glsnumtype @gloskip\endcsname{%
|
||||
\@gloskip}}%
|
||||
\ifthenelse{\equal{\@glodelim}{@dontchange@}}{}{%
|
||||
\expandafter\xdef\csname @\@glsnumtype @glodelim\endcsname{%
|
||||
\@glodelim}%
|
||||
}%
|
||||
}}
|
||||
\newcommand{\@gls@glossary@inext}{gls}
|
||||
\newcommand\printglossary[1][glossary]{%
|
||||
\def\@glostype{#1}%
|
||||
\@ifundefined{#1name}{%
|
||||
\renewcommand{\@glossaryname}{\glossaryname}}{%
|
||||
\renewcommand{\@glossaryname}{\csname #1name\endcsname}}%
|
||||
\@ifundefined{short#1name}{%
|
||||
\renewcommand{\@shortglossaryname}{\@glossaryname}}{%
|
||||
\renewcommand{\@shortglossaryname}{\csname short#1name\endcsname}}%
|
||||
\expandafter\let\expandafter\gls@number\csname gls@#1@number\endcsname
|
||||
\@input@{\jobname.\csname @gls@#1@inext\endcsname}}
|
||||
\providecommand{\glossaryname}{Glossary}
|
||||
\newcommand{\shortglossaryname}{\glossaryname}
|
||||
\newcommand{\entryname}{Notation}
|
||||
\newcommand{\descriptionname}{Description}
|
||||
\newcommand{\istfilename}{\jobname.ist}
|
||||
\def\@glossaryname{\glossaryname}
|
||||
\def\@shortglossaryname{\shortglossaryname}
|
||||
\newcommand{\@istfilename}[1]{}
|
||||
\providecommand{\glossarytitle}{%
|
||||
\@ifundefined{chapter}%
|
||||
{%
|
||||
\ifgls@hypertoc
|
||||
\phantomsection
|
||||
\@glosaddtoc{section}%
|
||||
\section*{\@glossaryname}\relax
|
||||
\else
|
||||
\section*{\@glossaryname}\relax
|
||||
\ifgls@toc\@glosaddtoc{section}\fi
|
||||
\fi}%
|
||||
{%
|
||||
\ifthenelse{\boolean{gls@section}}%
|
||||
{%
|
||||
\ifgls@hypertoc
|
||||
\phantomsection
|
||||
\@glosaddtoc{section}%
|
||||
\section*{\@glossaryname}\relax
|
||||
\else
|
||||
\section*{\@glossaryname}\relax
|
||||
\ifgls@toc\@glosaddtoc{section}\fi
|
||||
\fi}%
|
||||
{%
|
||||
\ifgls@hypertoc
|
||||
\@ifundefined{if@twoside}{%
|
||||
\clearpage}{%
|
||||
\if@twoside
|
||||
\@ifundefined{cleardoublepage}{\clearpage}{\cleardoublepage}%
|
||||
\else
|
||||
\clearpage
|
||||
\fi}%
|
||||
\phantomsection
|
||||
\@glosaddtoc{chapter}%
|
||||
\fi
|
||||
\chapter*{\@glossaryname}\relax
|
||||
\ifgls@toc\@glosaddtoc{chapter}\fi}}
|
||||
\markboth{\@shortglossaryname}{\@shortglossaryname}%
|
||||
}
|
||||
\@ifundefined{theglossary}{%
|
||||
\newenvironment{theglossary}{}{}}{%
|
||||
\PackageWarning{glossary}{Redefining 'theglossary' environment}}
|
||||
\renewenvironment{theglossary}{%
|
||||
\glossarytitle
|
||||
\glossarypreamble\@bef@reglos}{\@ftergl@s\glossarypostamble}
|
||||
\newcommand{\glossarypreamble}{}
|
||||
\newcommand{\glossarypostamble}{}
|
||||
\newcommand{\@glosaddtoc}[1]{%
|
||||
\addcontentsline{toc}{#1}{\@shortglossaryname}
|
||||
}
|
||||
\newif\ifgloitemfirst
|
||||
\newcommand{\@bef@reglos}{\global\gloitemfirsttrue\beforeglossary}
|
||||
\newcommand{\@ftergl@s}{\afterglossary\global\gloitemfirstfalse}
|
||||
\newcommand{\glossaryalignment}{\relax}
|
||||
\newcommand{\@gls@align@glossary}{}
|
||||
\newcommand{\glosstail}{%
|
||||
\@ifundefined{@gls@tail@\@glostype}{%
|
||||
\PackageError{glossary}{No glossary tail defined for glossary
|
||||
type '\@glostype'}{}}{%
|
||||
\csname @gls@tail@\@glostype\endcsname}}
|
||||
\newcommand{\@gls@tail@glossary}{}
|
||||
\newcommand{\afterglossary}{%
|
||||
\@ifundefined{@gls@afterglos@\@glostype}{%
|
||||
\PackageError{glossary}{No after glossary defined for glossary
|
||||
type '\@glostype'}{}}{%
|
||||
\csname @gls@afterglos@\@glostype\endcsname}}
|
||||
\newcommand{\beforeglossary}{%
|
||||
\@ifundefined{@gls@beforeglos@\@glostype}{%
|
||||
\PackageError{glossary}{No before glossary defined for glossary
|
||||
type '\@glostype'}{}}{%
|
||||
\csname @gls@beforeglos@\@glostype\endcsname}}
|
||||
\newcommand{\@gls@beforeglos@glossary}{}
|
||||
\newcommand{\@gls@afterglos@glossary}{}
|
||||
\newcommand{\@glossary@glodelim}{}
|
||||
\newcommand{\@glossary@delimT}{}
|
||||
\newcommand{\glsafternum}{}
|
||||
\newcommand{\glsbeforenum}{}
|
||||
\newcommand{\@glossary@gloskip}{}
|
||||
\newcommand{\@glossary@gloitem}[1]{#1}
|
||||
\newcommand{\gls@setlist}[1][glossary]{%
|
||||
\expandafter\def\csname @gls@beforeglos@#1\endcsname{%
|
||||
\begin{description}}%
|
||||
\expandafter\def\csname @gls@afterglos@#1\endcsname{%
|
||||
\end{description}}%
|
||||
\expandafter\def\csname @#1@gloskip\endcsname{\indexspace}%
|
||||
\ifthenelse{\equal{\csname gls@#1@number\endcsname}{none}}{%
|
||||
\expandafter\def\csname @#1@glodelim\endcsname{}}{%
|
||||
\expandafter\def\csname @#1@glodelim\endcsname{, }}%
|
||||
\expandafter\def\csname @#1@gloitem\endcsname##1{\item[##1]}%
|
||||
\expandafter\def\csname @#1@delimT\endcsname{}
|
||||
}
|
||||
\newcommand{\gls@setaltlist}[1][glossary]{%
|
||||
\expandafter\def\csname @gls@beforeglos@#1\endcsname{%
|
||||
\begin{description}}%
|
||||
\expandafter\def\csname @gls@afterglos@#1\endcsname{%
|
||||
\end{description}}%
|
||||
\expandafter\def\csname @#1@gloskip\endcsname{\indexspace}%
|
||||
\expandafter\def\csname @#1@gloitem\endcsname##1{%
|
||||
\item[##1]\mbox{}\nopagebreak\par\nopagebreak}%
|
||||
\expandafter\def\csname @#1@glodelim\endcsname{ }%
|
||||
\expandafter\def\csname @#1@delimT\endcsname{}
|
||||
}
|
||||
\ifthenelse{\equal{\gls@style}{super}}{
|
||||
\IfFileExists{supertab.sty}{\RequirePackage{supertab}}
|
||||
{\IfFileExists{supertabular.sty}{\RequirePackage{supertabular}}
|
||||
{\PackageError{glossary}{Option "super" chosen, but can't find
|
||||
"supertab" package}{If you want the "super" option, you have to have
|
||||
the "supertab" package installed.}}}}
|
||||
{\RequirePackage{longtable}}
|
||||
\newlength{\descriptionwidth}
|
||||
\setlength{\descriptionwidth}{0.6\linewidth}
|
||||
\newcommand{\@glossaryheader}{%
|
||||
\@ifundefined{glossaryheader}{\csname @\@glostype @header\endcsname}
|
||||
{\glossaryheader}%
|
||||
\@ifundefined{glossarysubheader}{}{\glossarysubheader}%
|
||||
}
|
||||
\newcommand{\gls@setheader}[1][glossary]{%
|
||||
\ifthenelse{\equal{\gls@header}{none}}%
|
||||
{%
|
||||
\ifthenelse{\equal{\gls@border}{none}}
|
||||
{\expandafter\def\csname @#1@header\endcsname{}%
|
||||
}{\expandafter\def\csname @#1@header\endcsname{\hline}}%
|
||||
}{%
|
||||
\ifnum\gls@cols=2\relax
|
||||
\ifthenelse{\equal{\gls@border}{none}}
|
||||
{%
|
||||
\expandafter\def\csname @#1@header\endcsname{%
|
||||
\bfseries\entryname & \bfseries \descriptionname\\}}%
|
||||
{%
|
||||
\expandafter\def\csname @#1@header\endcsname{%
|
||||
\hline\bfseries\entryname & \bfseries\descriptionname
|
||||
\\\hline\hline}}%
|
||||
\else
|
||||
\ifthenelse{\equal{\gls@border}{none}}
|
||||
{%
|
||||
\expandafter\def\csname @#1@header\endcsname{%
|
||||
\bfseries\entryname & \bfseries \descriptionname &
|
||||
\bfseries \glspageheader \\}}%
|
||||
{%
|
||||
\expandafter\def\csname @#1@header\endcsname{%
|
||||
\hline\bfseries\entryname &\bfseries\descriptionname &
|
||||
\bfseries \glspageheader \\\hline\hline}}%
|
||||
\fi
|
||||
}}
|
||||
\newcommand*{\glspageheader}{}
|
||||
\newcommand{\gls@setalignment}[1][glossary]{%
|
||||
\ifthenelse{\equal{\gls@border}{none}}
|
||||
{
|
||||
\ifnum\gls@cols=2\relax
|
||||
\expandafter\def\csname @gls@align@#1\endcsname{%
|
||||
@{\hspace{\tabcolsep}\bfseries}lp{\descriptionwidth}}
|
||||
\else
|
||||
\expandafter\def\csname @gls@align@#1\endcsname{%
|
||||
@{\hspace{\tabcolsep}\bfseries}lp{\descriptionwidth}l}
|
||||
\fi
|
||||
\expandafter\def\csname @gls@tail@#1\endcsname{}%
|
||||
}{%
|
||||
\ifnum\gls@cols=2\relax
|
||||
\expandafter\def\csname @gls@align@#1\endcsname{%
|
||||
|@{\hspace{\tabcolsep}\bfseries
|
||||
}lp{\descriptionwidth}|}
|
||||
\else
|
||||
\expandafter\def\csname @gls@align@#1\endcsname{%
|
||||
|@{\hspace{\tabcolsep}\bfseries
|
||||
}lp{\descriptionwidth}l|}
|
||||
\fi
|
||||
\expandafter\def\csname @gls@tail@#1\endcsname{\hline}%
|
||||
}%
|
||||
\expandafter\def\csname @#1@delimT\endcsname{\\}
|
||||
\ifnum\gls@cols=2\relax
|
||||
\expandafter\def\csname @#1@gloskip\endcsname{& \\}%
|
||||
\ifthenelse{\equal{\csname gls@#1@number\endcsname}{none}}{%
|
||||
\expandafter\def\csname @#1@glodelim\endcsname{}}{%
|
||||
\expandafter\def\csname @#1@glodelim\endcsname{, }}%
|
||||
\else
|
||||
\expandafter\def\csname @#1@gloskip\endcsname{& & \\}%
|
||||
\expandafter\def\csname @#1@glodelim\endcsname{& }%
|
||||
\fi
|
||||
\expandafter\def\csname @#1@gloitem\endcsname##1{##1 &}%
|
||||
}
|
||||
\newcommand{\@st@rtglostable}[2]{%
|
||||
\gls@ta={\begin{#1}}\gls@tb=\expandafter{#2}%
|
||||
\edef\@st@rtglost@ble{\the\gls@ta{\the\gls@tb}}
|
||||
\@st@rtglost@ble}
|
||||
\newcommand{\gls@setsuper}[1][glossary]{%
|
||||
\gls@setalignment[#1]%
|
||||
\gls@setheader[#1]%
|
||||
\expandafter\def\csname @gls@beforeglos@#1\endcsname{%
|
||||
\tablehead{\@glossaryheader}\tabletail{\glosstail}%
|
||||
\if\glossaryalignment\relax
|
||||
\expandafter\let\expandafter\@glossaryalignment
|
||||
\csname @gls@align@#1\endcsname
|
||||
\else
|
||||
\let\@glossaryalignment\glossaryalignment
|
||||
\fi
|
||||
\@st@rtglostable{supertabular}\@glossaryalignment}
|
||||
\expandafter\def\csname @gls@afterglos@#1\endcsname{%
|
||||
\end{supertabular}}%
|
||||
}
|
||||
\newcommand{\gls@setlong}[1][glossary]{%
|
||||
\gls@setalignment[#1]%
|
||||
\gls@setheader[#1]%
|
||||
\expandafter\def\csname @gls@beforeglos@#1\endcsname{%
|
||||
\if\relax\glossaryalignment
|
||||
\expandafter\let\expandafter\@glossaryalignment
|
||||
\csname @gls@align@#1\endcsname
|
||||
\else
|
||||
\let\@glossaryalignment\glossaryalignment
|
||||
\fi
|
||||
\@st@rtglostable{longtable}{\@glossaryalignment}
|
||||
\@glossaryheader\endhead\glosstail\endfoot}
|
||||
\expandafter\def\csname @gls@afterglos@#1\endcsname{%
|
||||
\end{longtable}}%
|
||||
}
|
||||
\newcommand{\@setglossarystyle}[1][glossary]{%
|
||||
\@ifundefined{gls@set\gls@style}{%
|
||||
\PackageError{glossary}{Glossary style '\gls@style' undefined}{}}{%
|
||||
\ifthenelse{\equal{\gls@number}{}}{}{%
|
||||
\expandafter\edef\csname gls@#1@number\endcsname{\gls@number}%
|
||||
\@gls@setnumbering[#1]{\gls@number}%
|
||||
}%
|
||||
\csname gls@set\gls@style\endcsname[#1]}}
|
||||
\let\gls@number\gls@glossary@number
|
||||
\@setglossarystyle
|
||||
\define@key{glosstyle}
|
||||
{style}
|
||||
{\ifthenelse{\equal{#1}{list} \or \equal{#1}{altlist}
|
||||
\or \equal{#1}{super} \or \equal{#1}{long}}
|
||||
{\def\gls@style{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary style '#1'}
|
||||
{Available styles are: list, altlist, super and long}}}
|
||||
\define@key{glosstyle}
|
||||
{header}[plain]{\ifthenelse{\equal{#1}{none} \or \equal{#1}{plain}}
|
||||
{\def\gls@header{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary style '#1'}
|
||||
{Available styles are: none and plain}}}
|
||||
\define@key{glosstyle}
|
||||
{border}[plain]{\ifthenelse{\equal{#1}{none} \or \equal{#1}{plain}}
|
||||
{\def\gls@border{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary border '#1'}
|
||||
{Available styles are: none and plain}}}
|
||||
\define@key{glosstyle}{cols}{\gls@cols=#1\relax
|
||||
\ifthenelse{\gls@cols<2 \or \gls@cols>3}
|
||||
{\PackageError{glossary}
|
||||
{invalid number of columns}
|
||||
{The cols option can only be 2 or 3}}
|
||||
{}}
|
||||
\define@key{glosstyle}
|
||||
{number}
|
||||
{\ifthenelse{\equal{#1}{none}}
|
||||
{\def\gls@number{#1}}
|
||||
{\@ifundefined{c@#1}{
|
||||
\PackageError{glossary}
|
||||
{Unknown glossary number style '#1'}
|
||||
{You may either specify "none" or the name of a counter,
|
||||
e.g. "section"}\def\gls@number{page}}{\def\gls@number{#1}}}}
|
||||
\newcommand{\setglossarystyle}[2][glossary]{%
|
||||
\def\gls@number{}%
|
||||
\setkeys{glosstyle}{#2}%
|
||||
\@setglossarystyle[#1]%
|
||||
}
|
||||
\ifthenelse{\equal{\gls@glossary@number}{none} \and \gls@cols<3}{%
|
||||
\renewcommand{\@glossary@glodelim}{}}{}
|
||||
\newif\ifist
|
||||
\let\noist=\istfalse
|
||||
\if@filesw\isttrue\else\istfalse\fi
|
||||
\newwrite\istfile
|
||||
\catcode`\%11\relax
|
||||
\newcommand{\writeist}{
|
||||
\protected@write\@auxout{}{\protect\@istfilename{\istfilename}}
|
||||
\openout\istfile=\istfilename
|
||||
\write\istfile{% makeindex style file created by LaTeX for document "\jobname" on \the\year-\the\month-\the\day}
|
||||
\write\istfile{keyword "\string\\glossaryentry"}
|
||||
\write\istfile{preamble "\string\\begin{theglossary}"}
|
||||
\write\istfile{postamble "\string\n\string\\end{theglossary}\string\n"}
|
||||
\write\istfile{group_skip "\string\\gloskip "}
|
||||
\write\istfile{item_0 "\string\n\string\n\string\\gloitem "}
|
||||
\write\istfile{delim_0 "\string\n\string\\glodelim "}
|
||||
\write\istfile{page_compositor "\pagecompositor"}
|
||||
\write\istfile{delim_n "\string\\delimN "}
|
||||
\write\istfile{delim_r "\string\\delimR "}
|
||||
\write\istfile{delim_t "\string\\delimT "}
|
||||
\write\istfile{headings_flag 1}
|
||||
\write\istfile{heading_prefix "\string\\glogroup"}
|
||||
\write\istfile{symhead_positive "Symbols"}
|
||||
\write\istfile{numhead_positive "Numbers"}
|
||||
\closeout\istfile
|
||||
}
|
||||
\catcode`\%14\relax
|
||||
\renewcommand{\makeglossary}{
|
||||
\newwrite\@glossaryfile
|
||||
\immediate\openout\@glossaryfile=\jobname.glo
|
||||
\renewcommand{\glossary}[1][]{\gdef\@glo@l@bel{##1}%
|
||||
\@bsphack \begingroup \@wrglossary }
|
||||
\typeout {Writing glossary file \jobname .glo }
|
||||
\let \makeglossary \@empty
|
||||
\ifist\writeist\fi
|
||||
\noist}
|
||||
\renewcommand{\glossary}[1][]{%
|
||||
\@bsphack\begingroup\@sanitize\@index}
|
||||
\newcommand{\newglossarytype}[4][glg]{
|
||||
\@ifundefined{#2}{%
|
||||
\protected@write\@auxout{}{\@newglossarytype[#1]{#2}{#3}{#4}}%
|
||||
\def\@glstype{#2}\def\@glsout{#3}\def\@glsin{#4}%
|
||||
\expandafter\edef\csname gls@\@glstype @number\endcsname{%
|
||||
\gls@glossary@number}%
|
||||
\expandafter\gdef\csname glsX\@glstype Xnumformat\endcsname{%
|
||||
\glsXglossaryXnumformat}%
|
||||
\expandafter\gdef\csname @\@glstype @delimN\endcsname{%
|
||||
\@glossary@delimN}%
|
||||
\expandafter\gdef\csname @\@glstype @delimR\endcsname{%
|
||||
\@glossary@delimR}%
|
||||
\expandafter\gdef\csname @gls@\@glstype @inext\endcsname{#4}%
|
||||
\expandafter\def\csname @gls@#2@type\endcsname{#4}%
|
||||
\expandafter\edef\csname make\@glstype\endcsname{%
|
||||
\noexpand\@m@kegl@ss{\@glstype}{\@glsout}}
|
||||
\expandafter\edef\csname \@glstype\endcsname{%
|
||||
\noexpand\@gl@ss@ary{\@glstype}}
|
||||
\expandafter\edef\csname x\@glstype\endcsname{%
|
||||
\noexpand\@Gl@ss@ary{\@glstype}}
|
||||
\@namedef{print\@glstype}{%
|
||||
\printglossary[#2]}%
|
||||
}{\PackageError{glossary}{Command
|
||||
\expandafter\string\csname #2\endcsname \space already defined}{%
|
||||
You can't call your new glossary type '#2' because there already
|
||||
exists a command with this name}}%
|
||||
\@@n@wglostype}
|
||||
\newcommand{\@@n@wglostype}[1][]{%
|
||||
\setglossarystyle[\@glstype]{#1}}
|
||||
\newcommand{\@newglossarytype}[4][glg]{}
|
||||
\newcommand\@m@kegl@ss[2]{%
|
||||
\expandafter\newwrite\csname @#1file\endcsname
|
||||
\expandafter\immediate\expandafter
|
||||
\openout\csname @#1file\endcsname=\jobname.#2
|
||||
\typeout {Writing #1 file \jobname .#2 }
|
||||
\expandafter\let \csname make#1\endcsname \@empty
|
||||
\ifist\writeist\fi
|
||||
\expandafter\def\csname the#1num\endcsname{\thepage}
|
||||
\noist
|
||||
}
|
||||
\newcommand\@gl@ss@ary[2][]{\@ifundefined{@#2file}{%
|
||||
\@bsphack\begingroup\@sanitize \@index}{%
|
||||
\gdef\@glo@l@bel{#1}%
|
||||
\@bsphack \begingroup \@wrglossary[#2]}}
|
||||
\newcommand{\@Gl@ss@ary}{%
|
||||
\renewcommand{\@@wrglossary}[1]{%
|
||||
\glossref{\@glo@l@bel}{##1}\renewcommand{\@@wrglossary}{}}%
|
||||
\@gl@ss@ary}
|
||||
\@onlypreamble{\newglossarytype}
|
||||
\newcommand\@acrnmsh{}
|
||||
\newcommand\@sacrnmsh{}
|
||||
\newcommand\@acrnmln{}
|
||||
\newcommand\@acrnmcmd{}
|
||||
\newcommand\@acrnmgls{}
|
||||
\newcommand\@acrnmins{}
|
||||
\toksdef\@glo@tb=2
|
||||
\newcommand{\@acr@list}{}
|
||||
\newcommand{\@acr@addtolist}[1]{\edef\@glo@ta{#1}%
|
||||
\ifthenelse{\equal{\@acr@list}{}}{%
|
||||
\edef\@acr@list{\@glo@ta}}{%
|
||||
\@glo@tb=\expandafter{\@acr@list}%
|
||||
\edef\@acr@list{\the\@glo@tb,\@glo@ta}}}
|
||||
\newcommand{\@acronymnamefmt}{\glolong\ (\gloshort)}
|
||||
\newcommand{\setacronymnamefmt}[1]{\def\@acronymnamefmt{#1}}
|
||||
\newcommand{\@acronymdescfmt}{\glodesc}
|
||||
\newcommand{\setacronymdescfmt}[1]{\def\@acronymdescfmt{#1}}
|
||||
\newcommand{\acronymfont}[1]{#1}
|
||||
\newcommand{\newacronym}[4][]{%
|
||||
\ifthenelse{\equal{#1}{}}{\renewcommand\@acrnmcmd{#2}}{%
|
||||
\renewcommand\@acrnmcmd{#1}}
|
||||
\@ifundefined{\@acrnmcmd}{%
|
||||
\expandafter\newcommand\csname\@acrnmcmd short\endcsname{%
|
||||
#2\protect\glsxspace}
|
||||
\expandafter\newcommand\csname\@acrnmcmd @nx@short\endcsname{#2}
|
||||
\expandafter\newcommand\csname\@acrnmcmd long\endcsname{%
|
||||
#3\protect\glsxspace}
|
||||
\expandafter\newcommand\csname\@acrnmcmd @nx@long\endcsname{#3}
|
||||
\def\@acrn@entry{#4}%
|
||||
{%
|
||||
\expandafter\@gls@getdescr\expandafter{\@acrn@entry}%
|
||||
\let\glodesc\@glo@desc%
|
||||
\def\glolong{#3}%
|
||||
\@onelevel@sanitize\glolong
|
||||
\def\gloshort{\noexpand\acronymfont{#2}}%
|
||||
\@onelevel@sanitize\gloshort
|
||||
\expandafter\protected@xdef\expandafter\@acrnamefmt{\@acronymnamefmt}
|
||||
\expandafter\protected@xdef\expandafter\@acrdesc{\@acronymdescfmt}
|
||||
}%
|
||||
\@acr@addtolist{\@acrnmcmd}
|
||||
\@glo@tb=\expandafter{\@acrn@entry}%
|
||||
\protected@edef\@acr@glsentry{name={\@acrnamefmt},%
|
||||
format=glsnumformat,sort={\@acrnmcmd},\the\@glo@tb,%
|
||||
description={\@acrdesc}}%
|
||||
\@glo@tb=\expandafter{\@acr@glsentry}%
|
||||
\newboolean{\@acrnmcmd first}\setboolean{\@acrnmcmd first}{true}
|
||||
\expandafter\protected@edef\csname \@acrnmcmd\endcsname{%
|
||||
\noexpand\@ifstar{\csname @s@\@acrnmcmd\endcsname}{%
|
||||
\csname @\@acrnmcmd\endcsname}}
|
||||
\ifglshyperacronym % hyperlinks
|
||||
\expandafter\protected@edef\csname @\@acrnmcmd\endcsname{%
|
||||
\noexpand\ifthenelse{\noexpand\boolean{\@acrnmcmd first}}{%
|
||||
\csname\@acrnmcmd @nx@long\endcsname\noexpand\@acrnmins\
|
||||
(\noexpand\xacronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
})\noexpand\unsetacronym{\@acrnmcmd}%
|
||||
}{\noexpand\xacronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
\noexpand\@acrnmins}}\noexpand\glsxspace}
|
||||
\expandafter\protected@edef\csname @s@\@acrnmcmd\endcsname{%
|
||||
\noexpand\ifthenelse{\noexpand\boolean{\@acrnmcmd first}}{%
|
||||
\noexpand\expandafter\noexpand\MakeUppercase
|
||||
\csname\@acrnmcmd @nx@long\endcsname\noexpand\@acrnmins\
|
||||
(\noexpand\xacronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
})%
|
||||
\noexpand\unsetacronym{\@acrnmcmd}}{%
|
||||
\noexpand\xacronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\noexpand\expandafter\noexpand\MakeUppercase
|
||||
\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
\noexpand\@acrnmins}}\noexpand\glsxspace}
|
||||
\else % no hyperlinks
|
||||
\expandafter\protected@edef\csname @\@acrnmcmd\endcsname{%
|
||||
\noexpand\ifthenelse{\noexpand\boolean{\@acrnmcmd first}}{%
|
||||
\csname\@acrnmcmd @nx@long\endcsname\noexpand\@acrnmins\
|
||||
(\noexpand\acronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
})\noexpand\unsetacronym{\@acrnmcmd}%
|
||||
}{\noexpand\acronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
\noexpand\@acrnmins}}%
|
||||
\noexpand\glsxspace}
|
||||
\expandafter\protected@edef\csname @s@\@acrnmcmd\endcsname{%
|
||||
\noexpand\ifthenelse{\noexpand\boolean{\@acrnmcmd first}}{%
|
||||
\noexpand\expandafter
|
||||
\noexpand\MakeUppercase
|
||||
\csname\@acrnmcmd @nx@long\endcsname\noexpand\@acrnmins\
|
||||
(\noexpand\acronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
})%
|
||||
\noexpand\unsetacronym{\@acrnmcmd}}{%
|
||||
\noexpand\acronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\noexpand\expandafter\noexpand\MakeUppercase
|
||||
\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
\noexpand\@acrnmins}}\noexpand\glsxspace}
|
||||
\fi
|
||||
}{%
|
||||
\PackageError{glossary}{Command '\expandafter\string
|
||||
\csname\@acrnmcmd\endcsname' already defined}{%
|
||||
The command name specified by \string\newacronym already exists.}}}
|
||||
\newcommand{\useacronym}{\@ifstar\@suseacronym\@useacronym}
|
||||
\newcommand{\@suseacronym}[2][]{{\let\glsxspace\relax
|
||||
\def\@acrnmins{#1}\csname @s@#2\endcsname}%
|
||||
\setboolean{#2first}{false}}
|
||||
\newcommand{\@useacronym}[2][]{{\let\glsxspace\relax
|
||||
\def\@acrnmins{#1}\csname @#2\endcsname}%
|
||||
\setboolean{#2first}{false}}
|
||||
\newcommand{\acrln}{\@ifstar\@sacrln\@acrln}
|
||||
\newcommand{\@acrln}[1]{\@ifundefined{#1long}{%
|
||||
\PackageError{glossary}{Acronym '#1' has not been defined}{}}{%
|
||||
\csname#1@nx@long\endcsname}}
|
||||
\newcommand{\@sacrln}[1]{\@ifundefined{#1long}{%
|
||||
\PackageError{glossary}{Acronym '#1' has not been defined}{}}{%
|
||||
\expandafter\expandafter\expandafter
|
||||
\MakeUppercase\csname#1@nx@long\endcsname}}
|
||||
\newcommand{\acrsh}{\@ifstar\@sacrsh\@acrsh}
|
||||
\newcommand{\@acrsh}[1]{\@ifundefined{#1short}{%
|
||||
\PackageError{glossary}{Acronym '#1' has not been defined}{}}{%
|
||||
\acronymfont{\csname#1@nx@short\endcsname}}}
|
||||
\newcommand{\@sacrsh}[1]{\@ifundefined{#1short}{%
|
||||
\PackageError{glossary}{Acronym '#1' has not been defined}{}}{%
|
||||
\acronymfont{\expandafter\expandafter\expandafter
|
||||
\MakeUppercase\csname#1@nx@short\endcsname}}}
|
||||
\newcommand{\ifacronymfirstuse}[3]{%
|
||||
\@ifundefined{if#1first}{%
|
||||
\PackageError{glossary}{Acronym '#1' not defined}{}}{%
|
||||
\ifthenelse{\boolean{#1first}}{#2}{#3}}}
|
||||
\newcommand{\resetacronym}[1]{%
|
||||
\@ifundefined{if#1first}{%
|
||||
\PackageError{glossary}{Acronym '#1' not defined}{}}{%
|
||||
\ifglsglobal
|
||||
\expandafter\global\csname #1firsttrue\endcsname
|
||||
\else
|
||||
\setboolean{#1first}{true}%
|
||||
\fi}}
|
||||
\newcommand{\unsetacronym}[1]{%
|
||||
\@ifundefined{if#1first}{%
|
||||
\PackageError{glossary}{Acronym '#1' not defined}{}}{%
|
||||
\ifglsglobal
|
||||
\expandafter\global\csname #1firstfalse\endcsname
|
||||
\else
|
||||
\setboolean{#1first}{false}%
|
||||
\fi}}
|
||||
\newcommand{\resetallacronyms}{%
|
||||
\@for\@acr:=\@acr@list\do{\resetacronym{\@acr}}}
|
||||
\newcommand{\unsetallacronyms}{%
|
||||
\@for\@acr:=\@acr@list\do{\unsetacronym{\@acr}}}
|
||||
\ifglsacronym
|
||||
\newglossarytype[alg]{acronym}{acr}{acn}
|
||||
\providecommand{\acronymname}{List of Acronyms}
|
||||
\else
|
||||
\let\acronym=\glossary
|
||||
\let\xacronym=\xglossary
|
||||
\fi
|
||||
\ifglshyper
|
||||
\def\glshyper#1#2{\@glshyper{#1}#2\delimR \delimR \\}
|
||||
\def\@glshyper#1#2\delimR #3\delimR #4\\{%
|
||||
\ifx\\#3\\%
|
||||
\@delimNhyper{#1}{#2}%
|
||||
\else
|
||||
\@ifundefined{hyperlink}{#2\delimR #3}{%
|
||||
\hyperlink{#1.#2}{#2}\delimR \hyperlink{#1.#3}{#3}}%
|
||||
\fi
|
||||
}
|
||||
\def\@delimNhyper#1#2{\@@delimNhyper{#1}#2\delimN \delimN\\}
|
||||
\def\@@delimNhyper#1#2\delimN #3\delimN #4\\{%
|
||||
\ifx\\#3\\%
|
||||
\@ifundefined{hyperlink}{#2}{\hyperlink{#1.#2}{#2}}%
|
||||
\else
|
||||
\@ifundefined{hyperlink}{#2\delimN #3}{%
|
||||
\hyperlink{#1.#2}{#2}\delimN \hyperlink{#1.#3}{#3}}%
|
||||
\fi
|
||||
}
|
||||
\newcommand\glshyperpage[1]{\glshyper{page}{#1}}
|
||||
\newcommand\glshypersection[1]{\glshyper{section}{#1}}
|
||||
\@ifundefined{chapter}
|
||||
{}
|
||||
{\let\@gls@old@chapter\@chapter
|
||||
\def\@chapter[#1]#2{\@gls@old@chapter[{#1}]{#2}%
|
||||
\@ifundefined{hyperdef}{}{\hyperdef{section}{\thesection}{}}}}
|
||||
\providecommand\hyperrm[2][\gls@number]{%
|
||||
\textrm{\glshyper{#1}{#2}}}
|
||||
\providecommand\hypersf[2][\gls@number]{%
|
||||
\textsf{\glshyper{#1}{#2}}}
|
||||
\providecommand\hypertt[2][\gls@number]{%
|
||||
\texttt{\glshyper{#1}{#2}}}
|
||||
\providecommand\hyperbf[2][\gls@number]{%
|
||||
\textbf{\glshyper{#1}{#2}}}
|
||||
\providecommand\hyperit[2][\gls@number]{%
|
||||
\textit{\glshyper{#1}{#2}}}
|
||||
\providecommand\hyperem[2][\gls@number]{%
|
||||
\emph{\glshyper{#1}{#2}}}
|
||||
\providecommand\hyperup[2][\gls@number]{%
|
||||
\textup{\glshyper{#1}{#2}}}
|
||||
\providecommand\hypersl[2][\gls@number]{%
|
||||
\textsl{\glshyper{#1}{#2}}}
|
||||
\providecommand\hypersc[2][\gls@number]{%
|
||||
\textsc{\glshyper{#1}{#2}}}
|
||||
\providecommand\hypermd[2][\gls@number]{%
|
||||
\textmd{\glshyper{#1}{#2}}}
|
||||
\else
|
||||
\providecommand\hyperrm[2][]{\textrm{#2}}
|
||||
\providecommand\hypersf[2][]{\textsf{#2}}
|
||||
\providecommand\hypertt[2][]{\texttt{#2}}
|
||||
\providecommand\hypermd[2][]{\textmd{#2}}
|
||||
\providecommand\hyperbf[2][]{\textbf{#2}}
|
||||
\providecommand\hyperit[2][]{\textit{#2}}
|
||||
\providecommand\hypersl[2][]{\textsl{#2}}
|
||||
\providecommand\hyperup[2][]{\textup{#2}}
|
||||
\providecommand\hypersc[2][]{\textsc{#2}}
|
||||
\providecommand\hyperem[2][]{\emph{#2}}
|
||||
\fi
|
||||
\endinput
|
||||
%%
|
||||
%% End of file `glossary.sty'.
|
115
docs/ProgrammingCryptol/utils/glossary/CHANGES
Normal file
115
docs/ProgrammingCryptol/utils/glossary/CHANGES
Normal file
@ -0,0 +1,115 @@
|
||||
glossary.sty history:
|
||||
|
||||
* Version 2.4: fixed problems caused by \@sanitize.
|
||||
Extended package option "number" to be used with
|
||||
any counter (not just page or section). Added
|
||||
number key to \setglossarystyle. Removed
|
||||
some redundant code. Fixed problems caused with
|
||||
hyperlinks when using a mixture of counters for
|
||||
individual entries. Added extra \hyper<xx> page
|
||||
formats. Added hook to provide a sub header when
|
||||
using a tabular style glossary. Added means of
|
||||
specifying a column header for page list column.
|
||||
Added facility to insert text between groups.
|
||||
Fixed bug in documentation when omitting \OnlyDescription
|
||||
|
||||
*** Note that if you update to version 2.4, it ***
|
||||
*** is advisable to delete your .gls etc files ***
|
||||
*** before recompiling. ***
|
||||
|
||||
|
||||
* Version 2.38: fixed by where inappropriate spaces are
|
||||
inserted when using xspace package.
|
||||
|
||||
* Version 2.37: fixed hypertoc to work with sections
|
||||
|
||||
* Version 2.36: added \useglosentry{*}. Fixed bug which
|
||||
allowed a pagebreak to occur between entry name and
|
||||
entry description when using the altlist style.
|
||||
|
||||
* Version 2.35: fixed makeglos.bat
|
||||
|
||||
* Version 2.34: \acronymname now defined using
|
||||
\providecommand instead of \newcommand. Fixed bug
|
||||
that prevented redefinition of \glossaryalignment.
|
||||
|
||||
* Version 2.33: fixed bug that occurs when a comma is
|
||||
used in the description field of \newacronym.
|
||||
|
||||
* Version 2.32: added \setacronymdescfmt. (Makes it
|
||||
easier to align the list of acronyms with
|
||||
acronym in one column and the long name in the
|
||||
second column.)
|
||||
|
||||
* Version 2.31: added global package option. Added
|
||||
\unsetacronym and \unsetallacronyms.
|
||||
|
||||
* Version 2.3: Made it easier to have multiple glossaries
|
||||
with different styles within the same document. Added
|
||||
facility for inserting text before and after the list of
|
||||
page numbers.
|
||||
|
||||
* Version 2.26: Fixed bug in \useacronym (optional argument
|
||||
was ignored in certain situations).
|
||||
|
||||
* Version 2.25: Minor bug fix (missing page delimiters).
|
||||
|
||||
* Version 2.24: Added hypertoc option, and changed the
|
||||
hyperlink targets in the glossary entries.
|
||||
|
||||
* Version 2.23: Fixed bug in hyperlinks caused by \glsxspace.
|
||||
|
||||
* Version 2.22: Added acronymfont. Added xspace support.
|
||||
Changed makeglos.pl so that it reads information from
|
||||
auxiliary file. Added makeglos.bat file
|
||||
|
||||
* Version 2.21: Added \resetallacronyms
|
||||
|
||||
* Version 2.2: \glossaryname is now defined using
|
||||
\providecommand instead of \newcommand. Checks if
|
||||
theglossary environment is already defined, and if so
|
||||
redefines it and issues a warning.
|
||||
|
||||
* Version 2.19: fixed bug in \storeglosentry.
|
||||
|
||||
* Version 2.18: fixed bug in \useacronym. Added \gls.
|
||||
|
||||
* Version 2.17: added acronym package option. Added
|
||||
\storeglosentry (replacing old \saveglosentry command)
|
||||
|
||||
* Version 2.16: fixed bug preventing changes to \glossaryname
|
||||
and \shortglossary name from having an effect.
|
||||
|
||||
* Version 2.15: added \shortglossaryname (for page header and
|
||||
table of contents)
|
||||
|
||||
* Version 2.14: added LaTeX2HTML support, added \xglossary
|
||||
command (provides hyperlink to relevent entry in the
|
||||
glossary), added -m switch to makeglos.pl (merges multiple
|
||||
entries with the same name but different descriptions).
|
||||
|
||||
* Version 2.13: added extra package option "hyperacronym".
|
||||
|
||||
* Version 2.12: mostly bug fixes, also added extra package
|
||||
option "section".
|
||||
|
||||
* Version 2.11: starred form of acronym defined. Added
|
||||
\useacronym.
|
||||
|
||||
* Version 2.1: fixed conflict with array package. Fixed
|
||||
problems which occured when using certain commands (such as
|
||||
\cite) in the last argument of \newacronym.
|
||||
|
||||
* Version 2.01: fixed conflict with datetime package.
|
||||
|
||||
* Version 2.0: provides the command \newacronym to define
|
||||
acronyms. Additional package options "toc" (add glossary to
|
||||
table of contents) and "hyper" use hyperlinks in the
|
||||
glossary.
|
||||
|
||||
* Version 1.1: provides the additional package option
|
||||
"number" which sets the associated glossary entry number to
|
||||
the page number (default), the section number or no number.
|
||||
Also provides the additional commands \glossarypreamble and
|
||||
\glossarypostamble
|
||||
|
45
docs/ProgrammingCryptol/utils/glossary/README
Normal file
45
docs/ProgrammingCryptol/utils/glossary/README
Normal file
@ -0,0 +1,45 @@
|
||||
LaTeX Package : glossary v 2.4
|
||||
|
||||
Last Modified : 20th July 2006
|
||||
|
||||
Author : Nicola Talbot
|
||||
|
||||
Files : glossary.dtx - documented source file
|
||||
glossary.ins - installation script
|
||||
|
||||
This package is provided to assist generating a glossary. It has
|
||||
a certain amount of flexibility allowing the user to customize the
|
||||
format of the glossary and define new glossary-style objects. It
|
||||
is also possible to define acronyms.
|
||||
|
||||
To extract the code do:
|
||||
|
||||
latex glossary.ins
|
||||
|
||||
This will create the files glossary.sty, glossary.perl,
|
||||
makeglos.pl and some sample files. Move
|
||||
glossary.sty to a subdirectory of your local texmf tree
|
||||
(e.g. $LOCALTEXMF/tex/latex/contrib/) and glossary.perl
|
||||
to the LaTeX2HTML style files directory (e.g. latex2html/styles).
|
||||
The Perl script makeglos.pl provides an easy interface to
|
||||
makeindex for those who can't remember (or can't be bothered) all
|
||||
the required switches. See documentation for more details.
|
||||
|
||||
To extract the documentation do:
|
||||
|
||||
latex glossary.dtx
|
||||
makeindex -s gind.ist glossary
|
||||
makeindex -s gglo.ist -o glossary.gls glossary.glo
|
||||
latex glossary.dtx
|
||||
latex glossary.dtx
|
||||
|
||||
Alternatively, if you use pdflatex instead of latex, the
|
||||
documentation will have hyperlinks. If you want documentation
|
||||
on the code, remove the line:
|
||||
\OnlyDescription
|
||||
|
||||
This material is subject to the LaTeX Project Public License.
|
||||
See http://www.ctan.org/tex-archive/help/Catalogue/licenses.lppl.html for the details of that license.
|
||||
|
||||
http://theoval.cmp.uea.ac.uk/~nlct/
|
||||
|
5915
docs/ProgrammingCryptol/utils/glossary/glossary.dtx
Normal file
5915
docs/ProgrammingCryptol/utils/glossary/glossary.dtx
Normal file
File diff suppressed because it is too large
Load Diff
38
docs/ProgrammingCryptol/utils/glossary/glossary.ins
Normal file
38
docs/ProgrammingCryptol/utils/glossary/glossary.ins
Normal file
@ -0,0 +1,38 @@
|
||||
% glossary.ins generated using makedtx version 0.91b 2006/7/25 18:13
|
||||
\input docstrip
|
||||
|
||||
\preamble
|
||||
Copyright (C) 2006 Nicola Talbot, all rights reserved.
|
||||
If you modify this file, you must change its name first.
|
||||
You are NOT ALLOWED to distribute this file alone. You are NOT
|
||||
ALLOWED to take money for the distribution or use of either this
|
||||
file or a changed version, except for a nominal charge for copying
|
||||
etc.
|
||||
\endpreamble
|
||||
|
||||
\askforoverwritefalse
|
||||
|
||||
\generate{\file{makeglos.pl}{\nopreamble\nopostamble\from{glossary.dtx}{makeglos.pl}}
|
||||
\file{sampleSec.tex}{\usepreamble\defaultpreamble
|
||||
\usepostamble\defaultpostamble\from{glossary.dtx}{sampleSec.tex,package}}
|
||||
\file{sampleNtn.tex}{\usepreamble\defaultpreamble
|
||||
\usepostamble\defaultpostamble\from{glossary.dtx}{sampleNtn.tex,package}}
|
||||
\file{sampleEqPg.tex}{\usepreamble\defaultpreamble
|
||||
\usepostamble\defaultpostamble\from{glossary.dtx}{sampleEqPg.tex,package}}
|
||||
\file{makeglos.bat}{\nopreamble\nopostamble\from{glossary.dtx}{makeglos.bat}}
|
||||
\file{sample.tex}{\usepreamble\defaultpreamble
|
||||
\usepostamble\defaultpostamble\from{glossary.dtx}{sample.tex,package}}
|
||||
\file{sampleNtn2.tex}{\usepreamble\defaultpreamble
|
||||
\usepostamble\defaultpostamble\from{glossary.dtx}{sampleNtn2.tex,package}}
|
||||
\file{glossary.perl}{\nopreamble\nopostamble\from{glossary.dtx}{glossary.perl}}
|
||||
\file{glossary.sty}{\usepreamble\defaultpreamble
|
||||
\usepostamble\defaultpostamble\from{glossary.dtx}{glossary.sty,package}}
|
||||
\file{sample4col.tex}{\usepreamble\defaultpreamble
|
||||
\usepostamble\defaultpostamble\from{glossary.dtx}{sample4col.tex,package}}
|
||||
\file{sampleAcr.tex}{\usepreamble\defaultpreamble
|
||||
\usepostamble\defaultpostamble\from{glossary.dtx}{sampleAcr.tex,package}}
|
||||
\file{sampleEq.tex}{\usepreamble\defaultpreamble
|
||||
\usepostamble\defaultpostamble\from{glossary.dtx}{sampleEq.tex,package}}
|
||||
}
|
||||
|
||||
\endbatchfile
|
BIN
docs/ProgrammingCryptol/utils/glossary/glossary.pdf
Normal file
BIN
docs/ProgrammingCryptol/utils/glossary/glossary.pdf
Normal file
Binary file not shown.
1055
docs/ProgrammingCryptol/utils/glossary/glossary.perl
Normal file
1055
docs/ProgrammingCryptol/utils/glossary/glossary.perl
Normal file
File diff suppressed because it is too large
Load Diff
979
docs/ProgrammingCryptol/utils/glossary/glossary.sty
Normal file
979
docs/ProgrammingCryptol/utils/glossary/glossary.sty
Normal file
@ -0,0 +1,979 @@
|
||||
%%
|
||||
%% This is file `glossary.sty',
|
||||
%% generated with the docstrip utility.
|
||||
%%
|
||||
%% The original source files were:
|
||||
%%
|
||||
%% glossary.dtx (with options: `glossary.sty,package')
|
||||
%% Copyright (C) 2006 Nicola Talbot, all rights reserved.
|
||||
%% If you modify this file, you must change its name first.
|
||||
%% You are NOT ALLOWED to distribute this file alone. You are NOT
|
||||
%% ALLOWED to take money for the distribution or use of either this
|
||||
%% file or a changed version, except for a nominal charge for copying
|
||||
%% etc.
|
||||
%% \CharacterTable
|
||||
%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
|
||||
%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
|
||||
%% Digits \0\1\2\3\4\5\6\7\8\9
|
||||
%% Exclamation \! Double quote \" Hash (number) \#
|
||||
%% Dollar \$ Percent \% Ampersand \&
|
||||
%% Acute accent \' Left paren \( Right paren \)
|
||||
%% Asterisk \* Plus \+ Comma \,
|
||||
%% Minus \- Point \. Solidus \/
|
||||
%% Colon \: Semicolon \; Less than \<
|
||||
%% Equals \= Greater than \> Question mark \?
|
||||
%% Commercial at \@ Left bracket \[ Backslash \\
|
||||
%% Right bracket \] Circumflex \^ Underscore \_
|
||||
%% Grave accent \` Left brace \{ Vertical bar \|
|
||||
%% Right brace \} Tilde \~}
|
||||
\NeedsTeXFormat{LaTeX2e}
|
||||
\ProvidesPackage{glossary}[2006/07/20 2.4 (NLCT)]
|
||||
\RequirePackage{ifthen}
|
||||
\RequirePackage{keyval}
|
||||
\define@key{gloss}
|
||||
{style}
|
||||
{\ifthenelse{\equal{#1}{list} \or \equal{#1}{altlist}
|
||||
\or \equal{#1}{super} \or \equal{#1}{long}}
|
||||
{\def\gls@style{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary style '#1'}
|
||||
{Available styles are: list, altlist, super and long}}}
|
||||
\define@key{gloss}
|
||||
{header}[plain]{\ifthenelse{\equal{#1}{none} \or \equal{#1}{plain}}
|
||||
{\def\gls@header{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary style '#1'}
|
||||
{Available styles are: none and plain}}}
|
||||
\define@key{gloss}
|
||||
{border}[plain]{\ifthenelse{\equal{#1}{none} \or \equal{#1}{plain}}
|
||||
{\def\gls@border{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary border '#1'}
|
||||
{Available styles are: none and plain}}}
|
||||
\newcount\gls@cols
|
||||
\define@key{gloss}{cols}{\gls@cols=#1\relax
|
||||
\ifthenelse{\gls@cols<2 \or \gls@cols>3}
|
||||
{\PackageError{glossary}
|
||||
{invalid number of columns}
|
||||
{The cols option can only be 2 or 3}}
|
||||
{}}
|
||||
\define@key{gloss}
|
||||
{number}
|
||||
{\ifthenelse{\equal{#1}{none}}
|
||||
{\def\gls@glossary@number{#1}}
|
||||
{\@ifundefined{c@#1}{
|
||||
\PackageError{glossary}
|
||||
{Unknown glossary number style '#1'}
|
||||
{You may either specify "none" or the name of a counter,
|
||||
e.g. "section"}\def\gls@glossary@number{page}}{\def\gls@glossary@number{#1}}}}
|
||||
\newif\ifgls@toc
|
||||
\define@key{gloss}{toc}[true]{\ifthenelse{\equal{#1}{true}
|
||||
\or \equal{#1}{false}}
|
||||
{\csname gls@toc#1\endcsname}
|
||||
{\PackageError{glossary}{Glossary option 'toc' is boolean}
|
||||
{The value of 'toc' can only be set to 'true' or 'false'}}}
|
||||
\newif\ifgls@hypertoc
|
||||
\define@key{gloss}{hypertoc}[true]{%
|
||||
\ifthenelse{\equal{#1}{true} \or \equal{#1}{false}}
|
||||
{\csname gls@hypertoc#1\endcsname}
|
||||
{\PackageError{glossary}{Glossary option 'hypertoc' is boolean}
|
||||
{The value of 'hypertoc' can only be set to 'true' or 'false'}}}
|
||||
\newif\ifgls@section
|
||||
\define@key{gloss}{section}[true]{%
|
||||
\ifthenelse{\equal{#1}{true} \or \equal{#1}{false}}
|
||||
{\csname gls@section#1\endcsname}
|
||||
{\PackageError{glossary}{Glossary option 'section' is boolean}
|
||||
{The value of 'section' can only be set to 'true' or 'false'}}}
|
||||
\gls@sectionfalse
|
||||
\newif\ifglshyper
|
||||
\newif\ifglshyperacronym
|
||||
\define@key{gloss}{hyper}[true]{%
|
||||
\ifthenelse{\equal{#1}{true} \or \equal{#1}{false}}
|
||||
{\csname glshyper#1\endcsname\glshyperacronymtrue}
|
||||
{\PackageError{glossary}{Glossary option 'hyper' is boolean}
|
||||
{The value of 'hyper' can only be set to 'true' or 'false'}}}
|
||||
\define@key{gloss}{hyperacronym}[true]{%
|
||||
\ifthenelse{\equal{#1}{true} \or \equal{#1}{false}}
|
||||
{\csname glshyperacronym#1\endcsname}
|
||||
{\PackageError{glossary}{Glossary option 'hyperacronym' is boolean}
|
||||
{The value of 'hyperacronym' can only be set to 'true' or 'false'}}}
|
||||
\newif\ifglsacronym
|
||||
\define@key{gloss}{acronym}[true]{%
|
||||
\ifthenelse{\equal{#1}{true} \or \equal{#1}{false}}
|
||||
{\setboolean{glsacronym}{#1}}{%
|
||||
\PackageError{glossary}{Glossary option 'acronym' is boolean}{The
|
||||
value of 'acronym' can only be set to 'true' or 'false'}}}
|
||||
\newif\ifglsglobal
|
||||
\define@key{gloss}{global}[true]{\ifthenelse{\equal{#1}{true}\or
|
||||
\equal{#1}{false}}{\setboolean{glsglobal}{#1}}{%
|
||||
\PackageError{glossary}{Glossary option 'global' is boolean}{The
|
||||
value of 'global' can only be set to 'true' or 'false'}}}
|
||||
\def\gls@style{long}
|
||||
\def\gls@header{none}
|
||||
\def\gls@border{none}
|
||||
\def\gls@glossary@number{page}
|
||||
\gls@cols=2\relax
|
||||
\gls@tocfalse
|
||||
\@ifundefined{hyperpage}{\glshyperfalse\glshyperacronymfalse}{%
|
||||
\glshypertrue\glshyperacronymtrue}
|
||||
\@ifundefined{hypertarget}{
|
||||
\newcommand{\glosslabel}[2]{#2}%
|
||||
\newcommand{\glossref}[2]{#2}%
|
||||
}{%
|
||||
\newcommand{\glosslabel}[2]{\hypertarget{#1}{#2}}%
|
||||
\newcommand{\glossref}[2]{\hyperlink{#1}{#2}}
|
||||
}
|
||||
\@ifundefined{xspace}{%
|
||||
\let\glsxspace\relax}{%
|
||||
\let\glsxspace\xspace}
|
||||
\let\glossaryalignment\relax
|
||||
\newcommand{\glossarypackageoptions}[1]{\setkeys{gloss}{#1}}
|
||||
\InputIfFileExists{glossary.cfg}{%
|
||||
\typeout{Glossary configuration file loaded}}{%
|
||||
\typeout{No configuration file glossary.cfg found}}
|
||||
\renewcommand{\glossarypackageoptions}[1]{%
|
||||
\PackageError{glossary}{Command \string\glossarypackageoptions
|
||||
^^Jcan only be used in configuration file}{}}
|
||||
\DeclareOption*{\edef\@pkg@ptions{\noexpand
|
||||
\setkeys{gloss}{\CurrentOption}}
|
||||
\ifthenelse{\equal{\CurrentOption}{}}{}{\@pkg@ptions}}
|
||||
\ProcessOptions
|
||||
\ifthenelse{\(\equal{\gls@style}{list} \or
|
||||
\equal{\gls@style}{altlist}\) \and
|
||||
\(\not\equal{\gls@header}{none} \or \not\equal{\gls@border}{none}
|
||||
\or \gls@cols=3\)}
|
||||
{\PackageError{glossary}{You can't have option 'style=list' or
|
||||
'style=altlist' in combination with any of the other style
|
||||
options}{The 'list' and 'altlist' options don't have a header,
|
||||
border or number of columns option.}}
|
||||
{}
|
||||
\ifthenelse{\boolean{gls@hypertoc} \and \boolean{gls@toc}}{%
|
||||
\PackageWarning{glossary}{Can't have both 'toc' and
|
||||
'hypertoc', ignoring 'toc' option}
|
||||
\ifgls@hypertoc\gls@tocfalse\fi}{}
|
||||
\define@key{wrgloss}{name}{%
|
||||
\def\@glo@n@me{#1}%
|
||||
\@onelevel@sanitize\@glo@n@me%
|
||||
\global\let\@glo@n@me\@glo@n@me}
|
||||
\define@key{wrgloss}{description}{%
|
||||
\def\@descr{#1}%
|
||||
\@onelevel@sanitize\@descr}
|
||||
\define@key{wrgloss}{sort}{%
|
||||
\def\@s@rt{#1}%
|
||||
\@onelevel@sanitize\@s@rt
|
||||
\global\let\@s@rt\@s@rt}
|
||||
\define@key{wrgloss}{format}{\def\@f@rm@t{#1}}
|
||||
\define@key{wrgloss}{number}{\def\@glo@num{#1}}
|
||||
\newcommand{\@@wrglossary}{}
|
||||
\newcommand{\@glo@l@bel}{}
|
||||
\newcommand{\@gls@glossary@type}{glo}
|
||||
\renewcommand{\@wrglossary}[2][glossary]{\relax
|
||||
\gdef\@glo@n@me{}\def\@descr{}\def\@s@rt{}\def\@f@rm@t{}%
|
||||
\edef\@glo@num{\csname gls@#1@number\endcsname}\relax
|
||||
\xdef\@pr@fix{\csname @gls@#1@type\endcsname}%
|
||||
\setkeys{wrgloss}{#2}\relax
|
||||
\ifthenelse{\equal{\@glo@num}{none}}{\def\@@glo@num{\thepage}}{%
|
||||
\@ifundefined{c@\@glo@num}{\PackageError{glossary}{%
|
||||
Not such counter '\@glo@num'}{The value of the 'number' key
|
||||
must be the name of a counter or the word "none"}%
|
||||
\def\@@glo@num{\thepage}}{%
|
||||
\edef\@@glo@num{\csname the\@glo@num\endcsname}}}%
|
||||
\ifthenelse{\equal{\@s@rt}{}}{\gdef\@s@rt{\@glo@n@me}}{}%
|
||||
\ifthenelse{\equal{\@glo@l@bel}{}}{%
|
||||
\gdef\@glo@l@bel{\@pr@fix:\@s@rt}}{}%
|
||||
\ifthenelse{\equal{\@f@rm@t}{}}
|
||||
{\expandafter\protected@write\csname @#1file\endcsname{}%
|
||||
{\string\glossaryentry{\@s@rt @{%
|
||||
\string\glosslabel{\@glo@l@bel}{\@glo@n@me}}\@descr
|
||||
\string\relax|glsnumformat}{\@@glo@num}}}
|
||||
{\ifthenelse{\equal{\@f@rm@t}{hyperrm} \or
|
||||
\equal{\@f@rm@t}{hypersf} \or \equal{\@f@rm@t}{hypertt}
|
||||
\or \equal{\@f@rm@t}{hypermd} \or \equal{\@f@rm@t}{hyperbf}
|
||||
\or \equal{\@f@rm@t}{hyperit} \or \equal{\@f@rm@t}{hyperem}
|
||||
\or \equal{\@f@rm@t}{hypersl} \or \equal{\@f@rm@t}{hyperup}
|
||||
\or \equal{\@f@rm@t}{hypersc}}
|
||||
{\expandafter\protected@write\csname @#1file\endcsname{}%
|
||||
{\string\glossaryentry{\@s@rt @{%
|
||||
\string\glosslabel{\@glo@l@bel}{\@glo@n@me}}\@descr
|
||||
\string\relax|\@f@rm@t[\@glo@num]}{\@@glo@num}}}
|
||||
{\expandafter\protected@write\csname @#1file\endcsname{}%
|
||||
{\string\glossaryentry{\@s@rt @{%
|
||||
\string\glosslabel{\@glo@l@bel}{\@glo@n@me}}\@descr
|
||||
\string\relax|\@f@rm@t}{\@@glo@num}}}}\relax
|
||||
\endgroup\@esphack
|
||||
\@@wrglossary
|
||||
}
|
||||
\define@key{wrnsgloss}{name}{\def\@glo@n@me{#1}}
|
||||
\define@key{wrnsgloss}{description}{\def\@descr{#1}}
|
||||
\define@key{wrnsgloss}{sort}{\def\@s@rt{#1}}
|
||||
\define@key{wrnsgloss}{format}{\def\@f@rm@t{#1}}
|
||||
\define@key{wrnsgloss}{number}{\def\@glo@num{#1}}
|
||||
\newcommand{\@gls@getn@me}[1]{%
|
||||
\def\@glo@n@me{}\setkeys{wrnsgloss}{#1}%
|
||||
}
|
||||
\newcommand{\@gls@getdescr}[1]{%
|
||||
\@bsphack\begingroup
|
||||
\def\@descr{}%
|
||||
\setkeys{wrgloss}{#1}%
|
||||
\global\let\@glo@desc\@descr
|
||||
\endgroup\@esphack
|
||||
}
|
||||
\newcommand{\xglossary}{\renewcommand{\@@wrglossary}[1]{%
|
||||
\glossref{\@glo@l@bel}{##1}\renewcommand{\@@wrglossary}{}}%
|
||||
\glossary}
|
||||
\newcommand*{\@glo@label@list}{}
|
||||
\toksdef\gls@ta=0 \toksdef\gls@tb=2
|
||||
\newcommand{\@glo@label@addtolist}[1]{%
|
||||
\gls@ta={{#1}}\gls@tb=\expandafter{\@glo@label@list}%
|
||||
\xdef\@glo@label@list{\the\gls@ta,\the\gls@tb}}
|
||||
\newcommand*{\storeglosentry}[3][glossary]{%
|
||||
\ifthenelse{\equal{#2}{*}}{%
|
||||
\PackageError{glossary}{Glossary label '*' invalid}{You can't have
|
||||
a glossary entry with a * as the label}}{%
|
||||
\@ifundefined{glo@#2@entry}{%
|
||||
\@glo@label@addtolist{#2}%
|
||||
\expandafter\def\csname glo@#2@type\endcsname{#1}%
|
||||
\expandafter\def\csname glo@#2@entry\endcsname{#3}%
|
||||
\@gls@getn@me{#3}%
|
||||
\expandafter\protected@edef\csname glo@#2@name\endcsname{\@glo@n@me}%
|
||||
}{%
|
||||
\PackageError{glossary}{Glossary entry '#2' already
|
||||
defined}{There already exists a glossary entry with the label '#2'}}}%
|
||||
}
|
||||
\providecommand{\useglosentry}[2][\relax]{%
|
||||
\ifthenelse{\equal{#2}{*}}{\@for\@glolab:=\@glo@label@list\do{%
|
||||
\ifthenelse{\equal{\@glolab}{}}{}{\useglosentry[#1]{\@glolab}}}}{%
|
||||
\@ifundefined{glo@#2@type}{%
|
||||
\PackageError{glossary}{Glossary entry '#2' undefined}{You need
|
||||
to define the entry using \string\storeglosentry\space before
|
||||
using it.}}{{%
|
||||
\edef\@glostype{\csname glo@#2@type\endcsname}%
|
||||
\@glo@tb=\expandafter\expandafter\expandafter
|
||||
{\csname glo@#2@entry\endcsname}%
|
||||
\ifx#1\relax
|
||||
\edef\@glo@cmd{\expandafter\noexpand
|
||||
\csname\@glostype\endcsname{\the\@glo@tb}}%
|
||||
\else
|
||||
\edef\@glo@cmd{\expandafter\noexpand
|
||||
\csname\@glostype\endcsname{\the\@glo@tb,#1}}%
|
||||
\fi
|
||||
\@glo@cmd
|
||||
}}}}
|
||||
\providecommand{\useGlosentry}[3][\relax]{%
|
||||
\@ifundefined{glo@#2@type}{%
|
||||
\PackageError{glossary}{Glossary entry '#2' undefined}{You need
|
||||
to define the entry using \string\storeglosentry\space before
|
||||
using it.}}{{%
|
||||
\edef\@glostype{x\csname glo@#2@type\endcsname}%
|
||||
\@glo@tb=\expandafter\expandafter\expandafter
|
||||
{\csname glo@#2@entry\endcsname}%
|
||||
\ifx#1\relax
|
||||
\edef\@glo@cmd{\expandafter\noexpand
|
||||
\csname\@glostype\endcsname{\the\@glo@tb}}%
|
||||
\else
|
||||
\edef\@glo@cmd{\expandafter\noexpand
|
||||
\csname\@glostype\endcsname{\the\@glo@tb,#1}}%
|
||||
\fi
|
||||
\@glo@cmd{#3}%
|
||||
}}}
|
||||
\newcommand{\gls}[2][\relax]{%
|
||||
\useGlosentry[#1]{#2}{%
|
||||
\csname glo@#2@name\endcsname}}
|
||||
\providecommand{\saveglosentry}[3][glossary]{%
|
||||
\PackageWarning{glossary}{\string\saveglosentry\space is obsolete,
|
||||
please use \string\storeglosentry\space instead}%
|
||||
\expandafter\def\csname glo@#2@type\endcsname{#1}%
|
||||
\expandafter\def\csname glo@#2@entry\endcsname{%
|
||||
name={#2},description={#3}}}
|
||||
\newcommand*{\@gls@setnumbering}[2][glossary]{%
|
||||
\ifthenelse{\equal{#2}{none}}{%
|
||||
\def\pagecompositor{-}
|
||||
\expandafter\def\csname @#1@delimN\endcsname{}
|
||||
\expandafter\def\csname @#1@delimR\endcsname{}
|
||||
\expandafter\def\csname glsX#1Xnumformat\endcsname##1{}}{%
|
||||
\ifthenelse{\equal{#2}{page}}{%
|
||||
\def\pagecompositor{-}}{%
|
||||
\def\pagecompositor{.}}
|
||||
\expandafter\def\csname @#1@delimN\endcsname{, }
|
||||
\expandafter\def\csname @#1@delimR\endcsname{--}
|
||||
\ifglshyper
|
||||
\expandafter\def\csname glsX#1Xnumformat\endcsname##1{%
|
||||
\hyperrm[#2]{##1}}%
|
||||
\else
|
||||
\expandafter\def\csname glsX#1Xnumformat\endcsname##1{##1}\fi
|
||||
}
|
||||
}
|
||||
\@gls@setnumbering{\gls@glossary@number}
|
||||
\newcommand{\glsnumformat}[1]{%
|
||||
\@ifundefined{\@glostype}{\def\@glostype{glossary}}{}%
|
||||
\@ifundefined{glsX\@glostype Xnumformat}{%
|
||||
\PackageError{glossary}{Glossary type '\@glostype' undefined}{}}{%
|
||||
\csname glsX\@glostype Xnumformat\endcsname{#1}}}
|
||||
\def\@glostype{glossary}
|
||||
\newcommand{\delimN}{\csname @\@glostype @delimN\endcsname}
|
||||
\newcommand{\delimR}{\csname @\@glostype @delimR\endcsname}
|
||||
\newcommand{\gloitem}{\csname @\@glostype @gloitem\endcsname}
|
||||
\newcommand{\gloskip}{\csname @\@glostype @gloskip\endcsname}
|
||||
\newcommand{\delimT}{\glsafternum
|
||||
\csname @\@glostype @delimT\endcsname}
|
||||
\newcommand{\glodelim}{\csname @\@glostype @glodelim\endcsname
|
||||
\glsbeforenum}
|
||||
\newcommand{\glogroupSymbols}{}
|
||||
\newcommand{\glogroupNumbers}{}
|
||||
\newcommand{\glogroupA}{}
|
||||
\newcommand{\glogroupB}{}
|
||||
\newcommand{\glogroupC}{}
|
||||
\newcommand{\glogroupD}{}
|
||||
\newcommand{\glogroupE}{}
|
||||
\newcommand{\glogroupF}{}
|
||||
\newcommand{\glogroupG}{}
|
||||
\newcommand{\glogroupH}{}
|
||||
\newcommand{\glogroupI}{}
|
||||
\newcommand{\glogroupJ}{}
|
||||
\newcommand{\glogroupK}{}
|
||||
\newcommand{\glogroupL}{}
|
||||
\newcommand{\glogroupM}{}
|
||||
\newcommand{\glogroupN}{}
|
||||
\newcommand{\glogroupO}{}
|
||||
\newcommand{\glogroupP}{}
|
||||
\newcommand{\glogroupQ}{}
|
||||
\newcommand{\glogroupR}{}
|
||||
\newcommand{\glogroupS}{}
|
||||
\newcommand{\glogroupT}{}
|
||||
\newcommand{\glogroupU}{}
|
||||
\newcommand{\glogroupV}{}
|
||||
\newcommand{\glogroupW}{}
|
||||
\newcommand{\glogroupX}{}
|
||||
\newcommand{\glogroupY}{}
|
||||
\newcommand{\glogroupZ}{}
|
||||
\define@key{glossnum}{glsnumformat}{\def\@glsnumformat{#1}}
|
||||
\define@key{glossnum}{type}{\def\@glsnumtype{#1}}
|
||||
\define@key{glossnum}{delimN}{\def\@delimN{#1}}
|
||||
\define@key{glossnum}{delimR}{\def\@delimR{#1}}
|
||||
\define@key{glossnum}{delimT}{\def\@delimT{#1}}
|
||||
\define@key{glossnum}{gloskip}{\def\@gloskip{#1}}
|
||||
\define@key{glossnum}{glodelim}{\def\@glodelim{#1}}
|
||||
\providecommand{\ignore}[1]{}
|
||||
\newcommand{\setglossary}[1]{%
|
||||
\def\@glsnumformat{}%
|
||||
\def\@glsnumtype{glossary}%
|
||||
\def\@delimN{@dontchange@}%
|
||||
\def\@delimR{@dontchange@}%
|
||||
\def\@delimT{@dontchange@}%
|
||||
\def\@gloskip{@dontchange@}%
|
||||
\def\@glodelim{@dontchange@}%
|
||||
\setkeys{glossnum}{#1}\relax
|
||||
\@ifundefined{print\@glsnumtype}{%
|
||||
\PackageError{glossary}{Invalid glossary type '\@glsnumtype'}{%
|
||||
Glossary type '\@glsnumtype' has not been defined}
|
||||
}{%
|
||||
\ifthenelse{\equal{\@glsnumformat}{}}{}{%
|
||||
\expandafter\xdef\csname glsX\@glsnumtype Xnumformat\endcsname{%
|
||||
\noexpand\csname\@glsnumformat\noexpand\endcsname}%
|
||||
\ifthenelse{\equal{\@glsnumformat}{ignore}}{%
|
||||
\expandafter\xdef\csname @\@glsnumtype @delimN\endcsname{}%
|
||||
\expandafter\xdef\csname @\@glsnumtype @delimR\endcsname{}%
|
||||
}{}%
|
||||
}%
|
||||
\ifthenelse{\equal{\@delimN}{@dontchange@}}{}{%
|
||||
\expandafter\xdef\csname @\@glsnumtype @delimN\endcsname{%
|
||||
\@delimN}}%
|
||||
\ifthenelse{\equal{\@delimR}{@dontchange@}}{}{%
|
||||
\expandafter\xdef\csname @\@glsnumtype @delimR\endcsname{%
|
||||
\@delimR}}%
|
||||
\ifthenelse{\equal{\@delimT}{@dontchange@}}{}{%
|
||||
\expandafter\xdef\csname @\@glsnumtype @delimT\endcsname{%
|
||||
\@delimT}}%
|
||||
\ifthenelse{\equal{\@gloskip}{@dontchange@}}{}{%
|
||||
\expandafter\xdef\csname @\@glsnumtype @gloskip\endcsname{%
|
||||
\@gloskip}}%
|
||||
\ifthenelse{\equal{\@glodelim}{@dontchange@}}{}{%
|
||||
\expandafter\xdef\csname @\@glsnumtype @glodelim\endcsname{%
|
||||
\@glodelim}%
|
||||
}%
|
||||
}}
|
||||
\newcommand{\@gls@glossary@inext}{gls}
|
||||
\newcommand\printglossary[1][glossary]{%
|
||||
\def\@glostype{#1}%
|
||||
\@ifundefined{#1name}{%
|
||||
\renewcommand{\@glossaryname}{\glossaryname}}{%
|
||||
\renewcommand{\@glossaryname}{\csname #1name\endcsname}}%
|
||||
\@ifundefined{short#1name}{%
|
||||
\renewcommand{\@shortglossaryname}{\@glossaryname}}{%
|
||||
\renewcommand{\@shortglossaryname}{\csname short#1name\endcsname}}%
|
||||
\expandafter\let\expandafter\gls@number\csname gls@#1@number\endcsname
|
||||
\@input@{\jobname.\csname @gls@#1@inext\endcsname}}
|
||||
\providecommand{\glossaryname}{Glossary}
|
||||
\newcommand{\shortglossaryname}{\glossaryname}
|
||||
\newcommand{\entryname}{Notation}
|
||||
\newcommand{\descriptionname}{Description}
|
||||
\newcommand{\istfilename}{\jobname.ist}
|
||||
\def\@glossaryname{\glossaryname}
|
||||
\def\@shortglossaryname{\shortglossaryname}
|
||||
\newcommand{\@istfilename}[1]{}
|
||||
\providecommand{\glossarytitle}{%
|
||||
\@ifundefined{chapter}%
|
||||
{%
|
||||
\ifgls@hypertoc
|
||||
\phantomsection
|
||||
\@glosaddtoc{section}%
|
||||
\section*{\@glossaryname}\relax
|
||||
\else
|
||||
\section*{\@glossaryname}\relax
|
||||
\ifgls@toc\@glosaddtoc{section}\fi
|
||||
\fi}%
|
||||
{%
|
||||
\ifthenelse{\boolean{gls@section}}%
|
||||
{%
|
||||
\ifgls@hypertoc
|
||||
\phantomsection
|
||||
\@glosaddtoc{section}%
|
||||
\section*{\@glossaryname}\relax
|
||||
\else
|
||||
\section*{\@glossaryname}\relax
|
||||
\ifgls@toc\@glosaddtoc{section}\fi
|
||||
\fi}%
|
||||
{%
|
||||
\ifgls@hypertoc
|
||||
\@ifundefined{if@twoside}{%
|
||||
\clearpage}{%
|
||||
\if@twoside
|
||||
\@ifundefined{cleardoublepage}{\clearpage}{\cleardoublepage}%
|
||||
\else
|
||||
\clearpage
|
||||
\fi}%
|
||||
\phantomsection
|
||||
\@glosaddtoc{chapter}%
|
||||
\fi
|
||||
\chapter*{\@glossaryname}\relax
|
||||
\ifgls@toc\@glosaddtoc{chapter}\fi}}
|
||||
\markboth{\@shortglossaryname}{\@shortglossaryname}%
|
||||
}
|
||||
\@ifundefined{theglossary}{%
|
||||
\newenvironment{theglossary}{}{}}{%
|
||||
\PackageWarning{glossary}{Redefining 'theglossary' environment}}
|
||||
\renewenvironment{theglossary}{%
|
||||
\glossarytitle
|
||||
\glossarypreamble\@bef@reglos}{\@ftergl@s\glossarypostamble}
|
||||
\newcommand{\glossarypreamble}{}
|
||||
\newcommand{\glossarypostamble}{}
|
||||
\newcommand{\@glosaddtoc}[1]{%
|
||||
\addcontentsline{toc}{#1}{\@shortglossaryname}
|
||||
}
|
||||
\newif\ifgloitemfirst
|
||||
\newcommand{\@bef@reglos}{\global\gloitemfirsttrue\beforeglossary}
|
||||
\newcommand{\@ftergl@s}{\afterglossary\global\gloitemfirstfalse}
|
||||
\newcommand{\glossaryalignment}{\relax}
|
||||
\newcommand{\@gls@align@glossary}{}
|
||||
\newcommand{\glosstail}{%
|
||||
\@ifundefined{@gls@tail@\@glostype}{%
|
||||
\PackageError{glossary}{No glossary tail defined for glossary
|
||||
type '\@glostype'}{}}{%
|
||||
\csname @gls@tail@\@glostype\endcsname}}
|
||||
\newcommand{\@gls@tail@glossary}{}
|
||||
\newcommand{\afterglossary}{%
|
||||
\@ifundefined{@gls@afterglos@\@glostype}{%
|
||||
\PackageError{glossary}{No after glossary defined for glossary
|
||||
type '\@glostype'}{}}{%
|
||||
\csname @gls@afterglos@\@glostype\endcsname}}
|
||||
\newcommand{\beforeglossary}{%
|
||||
\@ifundefined{@gls@beforeglos@\@glostype}{%
|
||||
\PackageError{glossary}{No before glossary defined for glossary
|
||||
type '\@glostype'}{}}{%
|
||||
\csname @gls@beforeglos@\@glostype\endcsname}}
|
||||
\newcommand{\@gls@beforeglos@glossary}{}
|
||||
\newcommand{\@gls@afterglos@glossary}{}
|
||||
\newcommand{\@glossary@glodelim}{}
|
||||
\newcommand{\@glossary@delimT}{}
|
||||
\newcommand{\glsafternum}{}
|
||||
\newcommand{\glsbeforenum}{}
|
||||
\newcommand{\@glossary@gloskip}{}
|
||||
\newcommand{\@glossary@gloitem}[1]{#1}
|
||||
\newcommand{\gls@setlist}[1][glossary]{%
|
||||
\expandafter\def\csname @gls@beforeglos@#1\endcsname{%
|
||||
\begin{description}}%
|
||||
\expandafter\def\csname @gls@afterglos@#1\endcsname{%
|
||||
\end{description}}%
|
||||
\expandafter\def\csname @#1@gloskip\endcsname{\indexspace}%
|
||||
\ifthenelse{\equal{\csname gls@#1@number\endcsname}{none}}{%
|
||||
\expandafter\def\csname @#1@glodelim\endcsname{}}{%
|
||||
\expandafter\def\csname @#1@glodelim\endcsname{, }}%
|
||||
\expandafter\def\csname @#1@gloitem\endcsname##1{\item[##1]}%
|
||||
\expandafter\def\csname @#1@delimT\endcsname{}
|
||||
}
|
||||
\newcommand{\gls@setaltlist}[1][glossary]{%
|
||||
\expandafter\def\csname @gls@beforeglos@#1\endcsname{%
|
||||
\begin{description}}%
|
||||
\expandafter\def\csname @gls@afterglos@#1\endcsname{%
|
||||
\end{description}}%
|
||||
\expandafter\def\csname @#1@gloskip\endcsname{\indexspace}%
|
||||
\expandafter\def\csname @#1@gloitem\endcsname##1{%
|
||||
\item[##1]\mbox{}\nopagebreak\par\nopagebreak}%
|
||||
\expandafter\def\csname @#1@glodelim\endcsname{ }%
|
||||
\expandafter\def\csname @#1@delimT\endcsname{}
|
||||
}
|
||||
\ifthenelse{\equal{\gls@style}{super}}{
|
||||
\IfFileExists{supertab.sty}{\RequirePackage{supertab}}
|
||||
{\IfFileExists{supertabular.sty}{\RequirePackage{supertabular}}
|
||||
{\PackageError{glossary}{Option "super" chosen, but can't find
|
||||
"supertab" package}{If you want the "super" option, you have to have
|
||||
the "supertab" package installed.}}}}
|
||||
{\RequirePackage{longtable}}
|
||||
\newlength{\descriptionwidth}
|
||||
\setlength{\descriptionwidth}{0.6\linewidth}
|
||||
\newcommand{\@glossaryheader}{%
|
||||
\@ifundefined{glossaryheader}{\csname @\@glostype @header\endcsname}
|
||||
{\glossaryheader}%
|
||||
\@ifundefined{glossarysubheader}{}{\glossarysubheader}%
|
||||
}
|
||||
\newcommand{\gls@setheader}[1][glossary]{%
|
||||
\ifthenelse{\equal{\gls@header}{none}}%
|
||||
{%
|
||||
\ifthenelse{\equal{\gls@border}{none}}
|
||||
{\expandafter\def\csname @#1@header\endcsname{}%
|
||||
}{\expandafter\def\csname @#1@header\endcsname{\hline}}%
|
||||
}{%
|
||||
\ifnum\gls@cols=2\relax
|
||||
\ifthenelse{\equal{\gls@border}{none}}
|
||||
{%
|
||||
\expandafter\def\csname @#1@header\endcsname{%
|
||||
\bfseries\entryname & \bfseries \descriptionname\\}}%
|
||||
{%
|
||||
\expandafter\def\csname @#1@header\endcsname{%
|
||||
\hline\bfseries\entryname & \bfseries\descriptionname
|
||||
\\\hline\hline}}%
|
||||
\else
|
||||
\ifthenelse{\equal{\gls@border}{none}}
|
||||
{%
|
||||
\expandafter\def\csname @#1@header\endcsname{%
|
||||
\bfseries\entryname & \bfseries \descriptionname &
|
||||
\bfseries \glspageheader \\}}%
|
||||
{%
|
||||
\expandafter\def\csname @#1@header\endcsname{%
|
||||
\hline\bfseries\entryname &\bfseries\descriptionname &
|
||||
\bfseries \glspageheader \\\hline\hline}}%
|
||||
\fi
|
||||
}}
|
||||
\newcommand*{\glspageheader}{}
|
||||
\newcommand{\gls@setalignment}[1][glossary]{%
|
||||
\ifthenelse{\equal{\gls@border}{none}}
|
||||
{
|
||||
\ifnum\gls@cols=2\relax
|
||||
\expandafter\def\csname @gls@align@#1\endcsname{%
|
||||
@{\hspace{\tabcolsep}\bfseries}lp{\descriptionwidth}}
|
||||
\else
|
||||
\expandafter\def\csname @gls@align@#1\endcsname{%
|
||||
@{\hspace{\tabcolsep}\bfseries}lp{\descriptionwidth}l}
|
||||
\fi
|
||||
\expandafter\def\csname @gls@tail@#1\endcsname{}%
|
||||
}{%
|
||||
\ifnum\gls@cols=2\relax
|
||||
\expandafter\def\csname @gls@align@#1\endcsname{%
|
||||
|@{\hspace{\tabcolsep}\bfseries
|
||||
}lp{\descriptionwidth}|}
|
||||
\else
|
||||
\expandafter\def\csname @gls@align@#1\endcsname{%
|
||||
|@{\hspace{\tabcolsep}\bfseries
|
||||
}lp{\descriptionwidth}l|}
|
||||
\fi
|
||||
\expandafter\def\csname @gls@tail@#1\endcsname{\hline}%
|
||||
}%
|
||||
\expandafter\def\csname @#1@delimT\endcsname{\\}
|
||||
\ifnum\gls@cols=2\relax
|
||||
\expandafter\def\csname @#1@gloskip\endcsname{& \\}%
|
||||
\ifthenelse{\equal{\csname gls@#1@number\endcsname}{none}}{%
|
||||
\expandafter\def\csname @#1@glodelim\endcsname{}}{%
|
||||
\expandafter\def\csname @#1@glodelim\endcsname{, }}%
|
||||
\else
|
||||
\expandafter\def\csname @#1@gloskip\endcsname{& & \\}%
|
||||
\expandafter\def\csname @#1@glodelim\endcsname{& }%
|
||||
\fi
|
||||
\expandafter\def\csname @#1@gloitem\endcsname##1{##1 &}%
|
||||
}
|
||||
\newcommand{\@st@rtglostable}[2]{%
|
||||
\gls@ta={\begin{#1}}\gls@tb=\expandafter{#2}%
|
||||
\edef\@st@rtglost@ble{\the\gls@ta{\the\gls@tb}}
|
||||
\@st@rtglost@ble}
|
||||
\newcommand{\gls@setsuper}[1][glossary]{%
|
||||
\gls@setalignment[#1]%
|
||||
\gls@setheader[#1]%
|
||||
\expandafter\def\csname @gls@beforeglos@#1\endcsname{%
|
||||
\tablehead{\@glossaryheader}\tabletail{\glosstail}%
|
||||
\if\glossaryalignment\relax
|
||||
\expandafter\let\expandafter\@glossaryalignment
|
||||
\csname @gls@align@#1\endcsname
|
||||
\else
|
||||
\let\@glossaryalignment\glossaryalignment
|
||||
\fi
|
||||
\@st@rtglostable{supertabular}\@glossaryalignment}
|
||||
\expandafter\def\csname @gls@afterglos@#1\endcsname{%
|
||||
\end{supertabular}}%
|
||||
}
|
||||
\newcommand{\gls@setlong}[1][glossary]{%
|
||||
\gls@setalignment[#1]%
|
||||
\gls@setheader[#1]%
|
||||
\expandafter\def\csname @gls@beforeglos@#1\endcsname{%
|
||||
\if\relax\glossaryalignment
|
||||
\expandafter\let\expandafter\@glossaryalignment
|
||||
\csname @gls@align@#1\endcsname
|
||||
\else
|
||||
\let\@glossaryalignment\glossaryalignment
|
||||
\fi
|
||||
\@st@rtglostable{longtable}{\@glossaryalignment}
|
||||
\@glossaryheader\endhead\glosstail\endfoot}
|
||||
\expandafter\def\csname @gls@afterglos@#1\endcsname{%
|
||||
\end{longtable}}%
|
||||
}
|
||||
\newcommand{\@setglossarystyle}[1][glossary]{%
|
||||
\@ifundefined{gls@set\gls@style}{%
|
||||
\PackageError{glossary}{Glossary style '\gls@style' undefined}{}}{%
|
||||
\ifthenelse{\equal{\gls@number}{}}{}{%
|
||||
\expandafter\edef\csname gls@#1@number\endcsname{\gls@number}%
|
||||
\@gls@setnumbering[#1]{\gls@number}%
|
||||
}%
|
||||
\csname gls@set\gls@style\endcsname[#1]}}
|
||||
\let\gls@number\gls@glossary@number
|
||||
\@setglossarystyle
|
||||
\define@key{glosstyle}
|
||||
{style}
|
||||
{\ifthenelse{\equal{#1}{list} \or \equal{#1}{altlist}
|
||||
\or \equal{#1}{super} \or \equal{#1}{long}}
|
||||
{\def\gls@style{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary style '#1'}
|
||||
{Available styles are: list, altlist, super and long}}}
|
||||
\define@key{glosstyle}
|
||||
{header}[plain]{\ifthenelse{\equal{#1}{none} \or \equal{#1}{plain}}
|
||||
{\def\gls@header{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary style '#1'}
|
||||
{Available styles are: none and plain}}}
|
||||
\define@key{glosstyle}
|
||||
{border}[plain]{\ifthenelse{\equal{#1}{none} \or \equal{#1}{plain}}
|
||||
{\def\gls@border{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary border '#1'}
|
||||
{Available styles are: none and plain}}}
|
||||
\define@key{glosstyle}{cols}{\gls@cols=#1\relax
|
||||
\ifthenelse{\gls@cols<2 \or \gls@cols>3}
|
||||
{\PackageError{glossary}
|
||||
{invalid number of columns}
|
||||
{The cols option can only be 2 or 3}}
|
||||
{}}
|
||||
\define@key{glosstyle}
|
||||
{number}
|
||||
{\ifthenelse{\equal{#1}{none}}
|
||||
{\def\gls@number{#1}}
|
||||
{\@ifundefined{c@#1}{
|
||||
\PackageError{glossary}
|
||||
{Unknown glossary number style '#1'}
|
||||
{You may either specify "none" or the name of a counter,
|
||||
e.g. "section"}\def\gls@number{page}}{\def\gls@number{#1}}}}
|
||||
\newcommand{\setglossarystyle}[2][glossary]{%
|
||||
\def\gls@number{}%
|
||||
\setkeys{glosstyle}{#2}%
|
||||
\@setglossarystyle[#1]%
|
||||
}
|
||||
\ifthenelse{\equal{\gls@glossary@number}{none} \and \gls@cols<3}{%
|
||||
\renewcommand{\@glossary@glodelim}{}}{}
|
||||
\newif\ifist
|
||||
\let\noist=\istfalse
|
||||
\if@filesw\isttrue\else\istfalse\fi
|
||||
\newwrite\istfile
|
||||
\catcode`\%11\relax
|
||||
\newcommand{\writeist}{
|
||||
\protected@write\@auxout{}{\protect\@istfilename{\istfilename}}
|
||||
\openout\istfile=\istfilename
|
||||
\write\istfile{% makeindex style file created by LaTeX for document "\jobname" on \the\year-\the\month-\the\day}
|
||||
\write\istfile{keyword "\string\\glossaryentry"}
|
||||
\write\istfile{preamble "\string\\begin{theglossary}"}
|
||||
\write\istfile{postamble "\string\n\string\\end{theglossary}\string\n"}
|
||||
\write\istfile{group_skip "\string\\gloskip "}
|
||||
\write\istfile{item_0 "\string\n\string\n\string\\gloitem "}
|
||||
\write\istfile{delim_0 "\string\n\string\\glodelim "}
|
||||
\write\istfile{page_compositor "\pagecompositor"}
|
||||
\write\istfile{delim_n "\string\\delimN "}
|
||||
\write\istfile{delim_r "\string\\delimR "}
|
||||
\write\istfile{delim_t "\string\\delimT "}
|
||||
\write\istfile{headings_flag 1}
|
||||
\write\istfile{heading_prefix "\string\\glogroup"}
|
||||
\write\istfile{symhead_positive "Symbols"}
|
||||
\write\istfile{numhead_positive "Numbers"}
|
||||
\closeout\istfile
|
||||
}
|
||||
\catcode`\%14\relax
|
||||
\renewcommand{\makeglossary}{
|
||||
\newwrite\@glossaryfile
|
||||
\immediate\openout\@glossaryfile=\jobname.glo
|
||||
\renewcommand{\glossary}[1][]{\gdef\@glo@l@bel{##1}%
|
||||
\@bsphack \begingroup \@wrglossary }
|
||||
\typeout {Writing glossary file \jobname .glo }
|
||||
\let \makeglossary \@empty
|
||||
\ifist\writeist\fi
|
||||
\noist}
|
||||
\renewcommand{\glossary}[1][]{%
|
||||
\@bsphack\begingroup\@sanitize\@index}
|
||||
\newcommand{\newglossarytype}[4][glg]{
|
||||
\@ifundefined{#2}{%
|
||||
\protected@write\@auxout{}{\@newglossarytype[#1]{#2}{#3}{#4}}%
|
||||
\def\@glstype{#2}\def\@glsout{#3}\def\@glsin{#4}%
|
||||
\expandafter\edef\csname gls@\@glstype @number\endcsname{%
|
||||
\gls@glossary@number}%
|
||||
\expandafter\gdef\csname glsX\@glstype Xnumformat\endcsname{%
|
||||
\glsXglossaryXnumformat}%
|
||||
\expandafter\gdef\csname @\@glstype @delimN\endcsname{%
|
||||
\@glossary@delimN}%
|
||||
\expandafter\gdef\csname @\@glstype @delimR\endcsname{%
|
||||
\@glossary@delimR}%
|
||||
\expandafter\gdef\csname @gls@\@glstype @inext\endcsname{#4}%
|
||||
\expandafter\def\csname @gls@#2@type\endcsname{#4}%
|
||||
\expandafter\edef\csname make\@glstype\endcsname{%
|
||||
\noexpand\@m@kegl@ss{\@glstype}{\@glsout}}
|
||||
\expandafter\edef\csname \@glstype\endcsname{%
|
||||
\noexpand\@gl@ss@ary{\@glstype}}
|
||||
\expandafter\edef\csname x\@glstype\endcsname{%
|
||||
\noexpand\@Gl@ss@ary{\@glstype}}
|
||||
\@namedef{print\@glstype}{%
|
||||
\printglossary[#2]}%
|
||||
}{\PackageError{glossary}{Command
|
||||
\expandafter\string\csname #2\endcsname \space already defined}{%
|
||||
You can't call your new glossary type '#2' because there already
|
||||
exists a command with this name}}%
|
||||
\@@n@wglostype}
|
||||
\newcommand{\@@n@wglostype}[1][]{%
|
||||
\setglossarystyle[\@glstype]{#1}}
|
||||
\newcommand{\@newglossarytype}[4][glg]{}
|
||||
\newcommand\@m@kegl@ss[2]{%
|
||||
\expandafter\newwrite\csname @#1file\endcsname
|
||||
\expandafter\immediate\expandafter
|
||||
\openout\csname @#1file\endcsname=\jobname.#2
|
||||
\typeout {Writing #1 file \jobname .#2 }
|
||||
\expandafter\let \csname make#1\endcsname \@empty
|
||||
\ifist\writeist\fi
|
||||
\expandafter\def\csname the#1num\endcsname{\thepage}
|
||||
\noist
|
||||
}
|
||||
\newcommand\@gl@ss@ary[2][]{\@ifundefined{@#2file}{%
|
||||
\@bsphack\begingroup\@sanitize \@index}{%
|
||||
\gdef\@glo@l@bel{#1}%
|
||||
\@bsphack \begingroup \@wrglossary[#2]}}
|
||||
\newcommand{\@Gl@ss@ary}{%
|
||||
\renewcommand{\@@wrglossary}[1]{%
|
||||
\glossref{\@glo@l@bel}{##1}\renewcommand{\@@wrglossary}{}}%
|
||||
\@gl@ss@ary}
|
||||
\@onlypreamble{\newglossarytype}
|
||||
\newcommand\@acrnmsh{}
|
||||
\newcommand\@sacrnmsh{}
|
||||
\newcommand\@acrnmln{}
|
||||
\newcommand\@acrnmcmd{}
|
||||
\newcommand\@acrnmgls{}
|
||||
\newcommand\@acrnmins{}
|
||||
\toksdef\@glo@tb=2
|
||||
\newcommand{\@acr@list}{}
|
||||
\newcommand{\@acr@addtolist}[1]{\edef\@glo@ta{#1}%
|
||||
\ifthenelse{\equal{\@acr@list}{}}{%
|
||||
\edef\@acr@list{\@glo@ta}}{%
|
||||
\@glo@tb=\expandafter{\@acr@list}%
|
||||
\edef\@acr@list{\the\@glo@tb,\@glo@ta}}}
|
||||
\newcommand{\@acronymnamefmt}{\glolong\ (\gloshort)}
|
||||
\newcommand{\setacronymnamefmt}[1]{\def\@acronymnamefmt{#1}}
|
||||
\newcommand{\@acronymdescfmt}{\glodesc}
|
||||
\newcommand{\setacronymdescfmt}[1]{\def\@acronymdescfmt{#1}}
|
||||
\newcommand{\acronymfont}[1]{#1}
|
||||
\newcommand{\newacronym}[4][]{%
|
||||
\ifthenelse{\equal{#1}{}}{\renewcommand\@acrnmcmd{#2}}{%
|
||||
\renewcommand\@acrnmcmd{#1}}
|
||||
\@ifundefined{\@acrnmcmd}{%
|
||||
\expandafter\newcommand\csname\@acrnmcmd short\endcsname{%
|
||||
#2\protect\glsxspace}
|
||||
\expandafter\newcommand\csname\@acrnmcmd @nx@short\endcsname{#2}
|
||||
\expandafter\newcommand\csname\@acrnmcmd long\endcsname{%
|
||||
#3\protect\glsxspace}
|
||||
\expandafter\newcommand\csname\@acrnmcmd @nx@long\endcsname{#3}
|
||||
\def\@acrn@entry{#4}%
|
||||
{%
|
||||
\expandafter\@gls@getdescr\expandafter{\@acrn@entry}%
|
||||
\let\glodesc\@glo@desc%
|
||||
\def\glolong{#3}%
|
||||
\@onelevel@sanitize\glolong
|
||||
\def\gloshort{\noexpand\acronymfont{#2}}%
|
||||
\@onelevel@sanitize\gloshort
|
||||
\expandafter\protected@xdef\expandafter\@acrnamefmt{\@acronymnamefmt}
|
||||
\expandafter\protected@xdef\expandafter\@acrdesc{\@acronymdescfmt}
|
||||
}%
|
||||
\@acr@addtolist{\@acrnmcmd}
|
||||
\@glo@tb=\expandafter{\@acrn@entry}%
|
||||
\protected@edef\@acr@glsentry{name={\@acrnamefmt},%
|
||||
format=glsnumformat,sort={\@acrnmcmd},\the\@glo@tb,%
|
||||
description={\@acrdesc}}%
|
||||
\@glo@tb=\expandafter{\@acr@glsentry}%
|
||||
\newboolean{\@acrnmcmd first}\setboolean{\@acrnmcmd first}{true}
|
||||
\expandafter\protected@edef\csname \@acrnmcmd\endcsname{%
|
||||
\noexpand\@ifstar{\csname @s@\@acrnmcmd\endcsname}{%
|
||||
\csname @\@acrnmcmd\endcsname}}
|
||||
\ifglshyperacronym % hyperlinks
|
||||
\expandafter\protected@edef\csname @\@acrnmcmd\endcsname{%
|
||||
\noexpand\ifthenelse{\noexpand\boolean{\@acrnmcmd first}}{%
|
||||
\csname\@acrnmcmd @nx@long\endcsname\noexpand\@acrnmins\
|
||||
(\noexpand\xacronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
})\noexpand\unsetacronym{\@acrnmcmd}%
|
||||
}{\noexpand\xacronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
\noexpand\@acrnmins}}\noexpand\glsxspace}
|
||||
\expandafter\protected@edef\csname @s@\@acrnmcmd\endcsname{%
|
||||
\noexpand\ifthenelse{\noexpand\boolean{\@acrnmcmd first}}{%
|
||||
\noexpand\expandafter\noexpand\MakeUppercase
|
||||
\csname\@acrnmcmd @nx@long\endcsname\noexpand\@acrnmins\
|
||||
(\noexpand\xacronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
})%
|
||||
\noexpand\unsetacronym{\@acrnmcmd}}{%
|
||||
\noexpand\xacronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\noexpand\expandafter\noexpand\MakeUppercase
|
||||
\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
\noexpand\@acrnmins}}\noexpand\glsxspace}
|
||||
\else % no hyperlinks
|
||||
\expandafter\protected@edef\csname @\@acrnmcmd\endcsname{%
|
||||
\noexpand\ifthenelse{\noexpand\boolean{\@acrnmcmd first}}{%
|
||||
\csname\@acrnmcmd @nx@long\endcsname\noexpand\@acrnmins\
|
||||
(\noexpand\acronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
})\noexpand\unsetacronym{\@acrnmcmd}%
|
||||
}{\noexpand\acronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
\noexpand\@acrnmins}}%
|
||||
\noexpand\glsxspace}
|
||||
\expandafter\protected@edef\csname @s@\@acrnmcmd\endcsname{%
|
||||
\noexpand\ifthenelse{\noexpand\boolean{\@acrnmcmd first}}{%
|
||||
\noexpand\expandafter
|
||||
\noexpand\MakeUppercase
|
||||
\csname\@acrnmcmd @nx@long\endcsname\noexpand\@acrnmins\
|
||||
(\noexpand\acronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
})%
|
||||
\noexpand\unsetacronym{\@acrnmcmd}}{%
|
||||
\noexpand\acronym{\the\@glo@tb}{%
|
||||
\noexpand\acronymfont{\noexpand\expandafter\noexpand\MakeUppercase
|
||||
\csname\@acrnmcmd @nx@short\endcsname}%
|
||||
\noexpand\@acrnmins}}\noexpand\glsxspace}
|
||||
\fi
|
||||
}{%
|
||||
\PackageError{glossary}{Command '\expandafter\string
|
||||
\csname\@acrnmcmd\endcsname' already defined}{%
|
||||
The command name specified by \string\newacronym already exists.}}}
|
||||
\newcommand{\useacronym}{\@ifstar\@suseacronym\@useacronym}
|
||||
\newcommand{\@suseacronym}[2][]{{\let\glsxspace\relax
|
||||
\def\@acrnmins{#1}\csname @s@#2\endcsname}%
|
||||
\setboolean{#2first}{false}}
|
||||
\newcommand{\@useacronym}[2][]{{\let\glsxspace\relax
|
||||
\def\@acrnmins{#1}\csname @#2\endcsname}%
|
||||
\setboolean{#2first}{false}}
|
||||
\newcommand{\acrln}{\@ifstar\@sacrln\@acrln}
|
||||
\newcommand{\@acrln}[1]{\@ifundefined{#1long}{%
|
||||
\PackageError{glossary}{Acronym '#1' has not been defined}{}}{%
|
||||
\csname#1@nx@long\endcsname}}
|
||||
\newcommand{\@sacrln}[1]{\@ifundefined{#1long}{%
|
||||
\PackageError{glossary}{Acronym '#1' has not been defined}{}}{%
|
||||
\expandafter\expandafter\expandafter
|
||||
\MakeUppercase\csname#1@nx@long\endcsname}}
|
||||
\newcommand{\acrsh}{\@ifstar\@sacrsh\@acrsh}
|
||||
\newcommand{\@acrsh}[1]{\@ifundefined{#1short}{%
|
||||
\PackageError{glossary}{Acronym '#1' has not been defined}{}}{%
|
||||
\acronymfont{\csname#1@nx@short\endcsname}}}
|
||||
\newcommand{\@sacrsh}[1]{\@ifundefined{#1short}{%
|
||||
\PackageError{glossary}{Acronym '#1' has not been defined}{}}{%
|
||||
\acronymfont{\expandafter\expandafter\expandafter
|
||||
\MakeUppercase\csname#1@nx@short\endcsname}}}
|
||||
\newcommand{\ifacronymfirstuse}[3]{%
|
||||
\@ifundefined{if#1first}{%
|
||||
\PackageError{glossary}{Acronym '#1' not defined}{}}{%
|
||||
\ifthenelse{\boolean{#1first}}{#2}{#3}}}
|
||||
\newcommand{\resetacronym}[1]{%
|
||||
\@ifundefined{if#1first}{%
|
||||
\PackageError{glossary}{Acronym '#1' not defined}{}}{%
|
||||
\ifglsglobal
|
||||
\expandafter\global\csname #1firsttrue\endcsname
|
||||
\else
|
||||
\setboolean{#1first}{true}%
|
||||
\fi}}
|
||||
\newcommand{\unsetacronym}[1]{%
|
||||
\@ifundefined{if#1first}{%
|
||||
\PackageError{glossary}{Acronym '#1' not defined}{}}{%
|
||||
\ifglsglobal
|
||||
\expandafter\global\csname #1firstfalse\endcsname
|
||||
\else
|
||||
\setboolean{#1first}{false}%
|
||||
\fi}}
|
||||
\newcommand{\resetallacronyms}{%
|
||||
\@for\@acr:=\@acr@list\do{\resetacronym{\@acr}}}
|
||||
\newcommand{\unsetallacronyms}{%
|
||||
\@for\@acr:=\@acr@list\do{\unsetacronym{\@acr}}}
|
||||
\ifglsacronym
|
||||
\newglossarytype[alg]{acronym}{acr}{acn}
|
||||
\providecommand{\acronymname}{List of Acronyms}
|
||||
\else
|
||||
\let\acronym=\glossary
|
||||
\let\xacronym=\xglossary
|
||||
\fi
|
||||
\ifglshyper
|
||||
\def\glshyper#1#2{\@glshyper{#1}#2\delimR \delimR \\}
|
||||
\def\@glshyper#1#2\delimR #3\delimR #4\\{%
|
||||
\ifx\\#3\\%
|
||||
\@delimNhyper{#1}{#2}%
|
||||
\else
|
||||
\@ifundefined{hyperlink}{#2\delimR #3}{%
|
||||
\hyperlink{#1.#2}{#2}\delimR \hyperlink{#1.#3}{#3}}%
|
||||
\fi
|
||||
}
|
||||
\def\@delimNhyper#1#2{\@@delimNhyper{#1}#2\delimN \delimN\\}
|
||||
\def\@@delimNhyper#1#2\delimN #3\delimN #4\\{%
|
||||
\ifx\\#3\\%
|
||||
\@ifundefined{hyperlink}{#2}{\hyperlink{#1.#2}{#2}}%
|
||||
\else
|
||||
\@ifundefined{hyperlink}{#2\delimN #3}{%
|
||||
\hyperlink{#1.#2}{#2}\delimN \hyperlink{#1.#3}{#3}}%
|
||||
\fi
|
||||
}
|
||||
\newcommand\glshyperpage[1]{\glshyper{page}{#1}}
|
||||
\newcommand\glshypersection[1]{\glshyper{section}{#1}}
|
||||
\@ifundefined{chapter}
|
||||
{}
|
||||
{\let\@gls@old@chapter\@chapter
|
||||
\def\@chapter[#1]#2{\@gls@old@chapter[{#1}]{#2}%
|
||||
\@ifundefined{hyperdef}{}{\hyperdef{section}{\thesection}{}}}}
|
||||
\providecommand\hyperrm[2][\gls@number]{%
|
||||
\textrm{\glshyper{#1}{#2}}}
|
||||
\providecommand\hypersf[2][\gls@number]{%
|
||||
\textsf{\glshyper{#1}{#2}}}
|
||||
\providecommand\hypertt[2][\gls@number]{%
|
||||
\texttt{\glshyper{#1}{#2}}}
|
||||
\providecommand\hyperbf[2][\gls@number]{%
|
||||
\textbf{\glshyper{#1}{#2}}}
|
||||
\providecommand\hyperit[2][\gls@number]{%
|
||||
\textit{\glshyper{#1}{#2}}}
|
||||
\providecommand\hyperem[2][\gls@number]{%
|
||||
\emph{\glshyper{#1}{#2}}}
|
||||
\providecommand\hyperup[2][\gls@number]{%
|
||||
\textup{\glshyper{#1}{#2}}}
|
||||
\providecommand\hypersl[2][\gls@number]{%
|
||||
\textsl{\glshyper{#1}{#2}}}
|
||||
\providecommand\hypersc[2][\gls@number]{%
|
||||
\textsc{\glshyper{#1}{#2}}}
|
||||
\providecommand\hypermd[2][\gls@number]{%
|
||||
\textmd{\glshyper{#1}{#2}}}
|
||||
\else
|
||||
\providecommand\hyperrm[2][]{\textrm{#2}}
|
||||
\providecommand\hypersf[2][]{\textsf{#2}}
|
||||
\providecommand\hypertt[2][]{\texttt{#2}}
|
||||
\providecommand\hypermd[2][]{\textmd{#2}}
|
||||
\providecommand\hyperbf[2][]{\textbf{#2}}
|
||||
\providecommand\hyperit[2][]{\textit{#2}}
|
||||
\providecommand\hypersl[2][]{\textsl{#2}}
|
||||
\providecommand\hyperup[2][]{\textup{#2}}
|
||||
\providecommand\hypersc[2][]{\textsc{#2}}
|
||||
\providecommand\hyperem[2][]{\emph{#2}}
|
||||
\fi
|
||||
\endinput
|
||||
%%
|
||||
%% End of file `glossary.sty'.
|
3
docs/ProgrammingCryptol/utils/glossary/makeglos.bat
Normal file
3
docs/ProgrammingCryptol/utils/glossary/makeglos.bat
Normal file
@ -0,0 +1,3 @@
|
||||
@rem = '-*- Perl -*-
|
||||
@echo off
|
||||
perl -S %~dp0makeglos.pl %*
|
304
docs/ProgrammingCryptol/utils/glossary/makeglos.pl
Normal file
304
docs/ProgrammingCryptol/utils/glossary/makeglos.pl
Normal file
@ -0,0 +1,304 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
# File : makeglos
|
||||
# Author : Nicola Talbot
|
||||
# Version : 1.5 (2006/07/20)
|
||||
# Description: simple Perl script that calls makeindex.
|
||||
# Intended for use with "glossary.sty" (saves having to remember
|
||||
# all the various switches)
|
||||
|
||||
use Getopt::Std;
|
||||
|
||||
if ($#ARGV < 0)
|
||||
{
|
||||
die "Syntax : $0 [-ilqrcgm] [-s sty] [-o gls] [-t log] [-p num] <filename>\n";
|
||||
}
|
||||
|
||||
getopt('sotp');
|
||||
getopts('ilqrcgm');
|
||||
|
||||
# define known extensions
|
||||
|
||||
%exttype = (
|
||||
glossary => {in=>'glo', out=>'gls', 'log'=>'glg'},
|
||||
);
|
||||
|
||||
$ext = '';
|
||||
|
||||
if (length(@ARGV[0]) < 4)
|
||||
{
|
||||
$name = @ARGV[0];
|
||||
}
|
||||
elsif (substr(@ARGV[0],-4,1) eq ".")
|
||||
{
|
||||
$name = substr(@ARGV[0],0,length(@ARGV[0])-4);
|
||||
|
||||
$ext = substr(@ARGV[0],-3,3);
|
||||
}
|
||||
else
|
||||
{
|
||||
$name = @ARGV[0];
|
||||
}
|
||||
|
||||
$istfile = "$name.ist";
|
||||
|
||||
# check log file for other glossary types
|
||||
# and for ist file name
|
||||
|
||||
if (open AUXFILE, "$name.aux")
|
||||
{
|
||||
while (<AUXFILE>)
|
||||
{
|
||||
if (m/\\\@newglossarytype\s*\[(.*)\]{(.*)}{(.*)}{(.*)}/)
|
||||
{
|
||||
$exttype{$2}{'in'} = $3;
|
||||
$exttype{$2}{'out'} = $4;
|
||||
$exttype{$2}{'log'} = $1;
|
||||
|
||||
if (!$opt_q)
|
||||
{
|
||||
print "added glossary type '$2' ($3,$4,$1)\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (m/\\\@istfilename\s*{([^}]*)}/)
|
||||
{
|
||||
$istfile = $1;
|
||||
}
|
||||
}
|
||||
|
||||
close AUXFILE;
|
||||
}
|
||||
else
|
||||
{
|
||||
print "unable to open $name.aux\n";
|
||||
}
|
||||
|
||||
# save all the general makeindex switches
|
||||
|
||||
$mkidxopts = '';
|
||||
|
||||
if ($opt_i)
|
||||
{
|
||||
$mkidxopts .= " -i";
|
||||
}
|
||||
|
||||
if ($opt_l)
|
||||
{
|
||||
$mkidxopts .= " -l";
|
||||
}
|
||||
|
||||
if ($opt_q)
|
||||
{
|
||||
$mkidxopts .= " -q";
|
||||
}
|
||||
|
||||
if ($opt_r)
|
||||
{
|
||||
$mkidxopts .= " -r";
|
||||
}
|
||||
|
||||
if ($opt_c)
|
||||
{
|
||||
$mkidxopts .= " -c";
|
||||
}
|
||||
|
||||
if ($opt_g)
|
||||
{
|
||||
$mkidxopts .= " -g";
|
||||
}
|
||||
|
||||
unless ($opt_p eq "")
|
||||
{
|
||||
$mkidxopts .= " -p $opt_p";
|
||||
}
|
||||
|
||||
unless ($opt_s eq "")
|
||||
{
|
||||
$istfile = $opt_s;
|
||||
}
|
||||
|
||||
if ($ext ne '')
|
||||
{
|
||||
%thistype = %{$exttype{'glossary'}}; #default
|
||||
|
||||
foreach $type (keys %exttype)
|
||||
{
|
||||
if ($exttype{$type}{'in'} eq $ext)
|
||||
{
|
||||
%thistype = %{$exttype{$type}};
|
||||
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
if ($opt_o eq "")
|
||||
{
|
||||
$outfile = "$name.$thistype{out}";
|
||||
}
|
||||
else
|
||||
{
|
||||
$outfile = $opt_o;
|
||||
}
|
||||
|
||||
if ($opt_t eq "")
|
||||
{
|
||||
$transcript = "$name.$thistype{'log'}";
|
||||
}
|
||||
else
|
||||
{
|
||||
$transcript = $opt_t;
|
||||
}
|
||||
|
||||
&makeindex("$name.$ext",$outfile,$transcript,$istfile,
|
||||
$mkidxopts,$opt_q,$opt_m);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach $type (keys %exttype)
|
||||
{
|
||||
%thistype = %{$exttype{$type}};
|
||||
|
||||
$inputfile = "$name.$thistype{in}";
|
||||
|
||||
if (-r $inputfile)
|
||||
{
|
||||
if ($opt_o eq "")
|
||||
{
|
||||
$outfile = "$name.$thistype{out}";
|
||||
}
|
||||
else
|
||||
{
|
||||
$outfile = $opt_o;
|
||||
}
|
||||
|
||||
if ($opt_t eq "")
|
||||
{
|
||||
$transcript = "$name.$thistype{'log'}";
|
||||
}
|
||||
else
|
||||
{
|
||||
$transcript = $opt_t;
|
||||
}
|
||||
|
||||
&makeindex($inputfile,$outfile,$transcript,
|
||||
$istfile,$mkidxopts,$opt_q,$opt_m);
|
||||
}
|
||||
elsif (!$opt_q)
|
||||
{
|
||||
print "no read access for '$inputfile'\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub makeindex{
|
||||
local($in,$out,$trans,$ist,$rest,$quiet,$merge) = @_;
|
||||
local($name,$cmdstr,$buffer,$n,$i,$j);
|
||||
local(@stuff,@item);
|
||||
|
||||
if ($merge)
|
||||
{
|
||||
$cmdstr = "$rest -s $ist -t $trans -o tmp_$out $in";
|
||||
}
|
||||
else
|
||||
{
|
||||
$cmdstr = "$rest -s $ist -t $trans -o $out $in";
|
||||
}
|
||||
|
||||
unless ($quiet)
|
||||
{
|
||||
print "makeindex $cmdstr\n";
|
||||
}
|
||||
|
||||
`makeindex $cmdstr`;
|
||||
|
||||
if ($merge)
|
||||
{
|
||||
print "Merging entries\n";
|
||||
|
||||
open INPUT, "<tmp_$out";
|
||||
|
||||
$buffer = "";
|
||||
|
||||
while (<INPUT>)
|
||||
{
|
||||
$buffer .= $_;
|
||||
}
|
||||
|
||||
close INPUT;
|
||||
|
||||
open OUTPUT, ">$out";
|
||||
|
||||
@stuff = split /\\gloitem /, $buffer;
|
||||
|
||||
$n = scalar(@stuff);
|
||||
|
||||
if ($n < 2)
|
||||
{
|
||||
print OUTPUT $buffer;
|
||||
}
|
||||
else
|
||||
{
|
||||
print OUTPUT $stuff[0];
|
||||
|
||||
for ($i = 1, $j=-1; $i < $n; $i++)
|
||||
{
|
||||
if ($stuff[$i]=~s/{\\glosslabel{(.+)}{(.+)}}//)
|
||||
{
|
||||
$name = $&;
|
||||
|
||||
if ($j==-1)
|
||||
{
|
||||
$j = 0;
|
||||
$item[0]{'name'} = $name;
|
||||
$item[0]{'desc'} = $stuff[$i];
|
||||
}
|
||||
else
|
||||
{
|
||||
# makeindex has already sorted the entries
|
||||
# alphabetically, so duplicate entries
|
||||
# will be one after the other
|
||||
|
||||
if ($item[$j]{'name'} eq $name)
|
||||
{
|
||||
$item[$j]{'desc'} .= $stuff[$i];
|
||||
|
||||
print "collating $name\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$j++;
|
||||
$item[$j]{'name'} = $name;
|
||||
$item[$j]{'desc'} = $stuff[$i];
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
print STDERR
|
||||
"unable to extract name from glossary item:\n",
|
||||
$stuff[$i];
|
||||
}
|
||||
}
|
||||
|
||||
for ($i=0; $i <= $j; $i++)
|
||||
{
|
||||
# remove all but the last \delimT
|
||||
while ($item[$i]{'desc'}=~s/\\delimT/$&/sg > 1)
|
||||
{
|
||||
$item[$i]{'desc'}=~s/\\delimT//s;
|
||||
}
|
||||
print OUTPUT "\\gloitem ", $item[$i]{'name'},
|
||||
$item[$i]{'desc'};
|
||||
}
|
||||
}
|
||||
|
||||
close OUTPUT;
|
||||
|
||||
print "Output written in $out\n";
|
||||
|
||||
unlink "tmp_$out" or print "Can't delete tmp_$out: $!\n";
|
||||
}
|
||||
}
|
||||
|
||||
1;
|
3069
docs/ProgrammingCryptol/utils/glossary/manual.html
Normal file
3069
docs/ProgrammingCryptol/utils/glossary/manual.html
Normal file
File diff suppressed because it is too large
Load Diff
95
docs/ProgrammingCryptol/utils/glossary/sample.tex
Normal file
95
docs/ProgrammingCryptol/utils/glossary/sample.tex
Normal file
@ -0,0 +1,95 @@
|
||||
%%
|
||||
%% This is file `sample.tex',
|
||||
%% generated with the docstrip utility.
|
||||
%%
|
||||
%% The original source files were:
|
||||
%%
|
||||
%% glossary.dtx (with options: `sample.tex,package')
|
||||
%% Copyright (C) 2006 Nicola Talbot, all rights reserved.
|
||||
%% If you modify this file, you must change its name first.
|
||||
%% You are NOT ALLOWED to distribute this file alone. You are NOT
|
||||
%% ALLOWED to take money for the distribution or use of either this
|
||||
%% file or a changed version, except for a nominal charge for copying
|
||||
%% etc.
|
||||
%% \CharacterTable
|
||||
%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
|
||||
%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
|
||||
%% Digits \0\1\2\3\4\5\6\7\8\9
|
||||
%% Exclamation \! Double quote \" Hash (number) \#
|
||||
%% Dollar \$ Percent \% Ampersand \&
|
||||
%% Acute accent \' Left paren \( Right paren \)
|
||||
%% Asterisk \* Plus \+ Comma \,
|
||||
%% Minus \- Point \. Solidus \/
|
||||
%% Colon \: Semicolon \; Less than \<
|
||||
%% Equals \= Greater than \> Question mark \?
|
||||
%% Commercial at \@ Left bracket \[ Backslash \\
|
||||
%% Right bracket \] Circumflex \^ Underscore \_
|
||||
%% Grave accent \` Left brace \{ Vertical bar \|
|
||||
%% Right brace \} Tilde \~}
|
||||
\documentclass[a4paper]{report}
|
||||
|
||||
\usepackage[plainpages=false,colorlinks]{hyperref}
|
||||
\usepackage{glossary}
|
||||
|
||||
\makeglossary
|
||||
|
||||
|
||||
\storeglosentry{glossary1}{name=glossary,
|
||||
description=1) list of technical words}
|
||||
|
||||
\storeglosentry{glossary2}{name=glossary,
|
||||
description=2) collection of glosses}
|
||||
|
||||
\storeglosentry{Perl}{name=\texttt{Perl},
|
||||
sort=Perl, % need a sort key because name contains a command
|
||||
description=A scripting language}
|
||||
|
||||
\storeglosentry{pagelist}{name=page list,
|
||||
description={a list of individual pages or page ranges,
|
||||
e.g.\ 1,2,4,7-9}}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\title{Sample Document Using glossary Package}
|
||||
\author{Nicola Talbot}
|
||||
\pagenumbering{alph}% prevent duplicate page link names if using PDF
|
||||
\maketitle
|
||||
|
||||
\pagenumbering{roman}
|
||||
\tableofcontents
|
||||
|
||||
\chapter{Introduction}
|
||||
\pagenumbering{arabic}
|
||||
|
||||
A \gls{glossary1} is a very useful addition to any
|
||||
technical document, although a \gls{glossary2} can
|
||||
also simply be a collection of glosses, which is
|
||||
another thing entirely.
|
||||
|
||||
Once you have run your document through \LaTeX, you
|
||||
will then need to run the \texttt{.glo} file through
|
||||
\texttt{makeindex}. You will need to set the output
|
||||
file so that it creates a \texttt{.gls} file instead
|
||||
of an \texttt{.ind} file, and change the name of
|
||||
the log file so that it doesn't overwrite the index
|
||||
log file (if you have an index for your document).
|
||||
Rather than having to remember all the command line
|
||||
switches, you can call the \gls{Perl} script
|
||||
\texttt{makeglos.pl} which provides a convenient
|
||||
wrapper.
|
||||
|
||||
If you have two terms with different meanings in your
|
||||
\gls{glossary1}, \texttt{makeindex} will of course treat them as two
|
||||
separate entries, however, some people prefer to
|
||||
merge them. This can be done using \texttt{makeglos.pl}, and
|
||||
passing the option \texttt{-m}.
|
||||
|
||||
If a comma appears within the name or description, grouping
|
||||
must be used: \gls{pagelist}.
|
||||
|
||||
\printglossary
|
||||
|
||||
\end{document}
|
||||
\endinput
|
||||
%%
|
||||
%% End of file `sample.tex'.
|
54
docs/ProgrammingCryptol/utils/glossary/sample4col.tex
Normal file
54
docs/ProgrammingCryptol/utils/glossary/sample4col.tex
Normal file
@ -0,0 +1,54 @@
|
||||
%%
|
||||
%% This is file `sample4col.tex',
|
||||
%% generated with the docstrip utility.
|
||||
%%
|
||||
%% The original source files were:
|
||||
%%
|
||||
%% glossary.dtx (with options: `sample4col.tex,package')
|
||||
%% Copyright (C) 2006 Nicola Talbot, all rights reserved.
|
||||
%% If you modify this file, you must change its name first.
|
||||
%% You are NOT ALLOWED to distribute this file alone. You are NOT
|
||||
%% ALLOWED to take money for the distribution or use of either this
|
||||
%% file or a changed version, except for a nominal charge for copying
|
||||
%% etc.
|
||||
%% \CharacterTable
|
||||
%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
|
||||
%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
|
||||
%% Digits \0\1\2\3\4\5\6\7\8\9
|
||||
%% Exclamation \! Double quote \" Hash (number) \#
|
||||
%% Dollar \$ Percent \% Ampersand \&
|
||||
%% Acute accent \' Left paren \( Right paren \)
|
||||
%% Asterisk \* Plus \+ Comma \,
|
||||
%% Minus \- Point \. Solidus \/
|
||||
%% Colon \: Semicolon \; Less than \<
|
||||
%% Equals \= Greater than \> Question mark \?
|
||||
%% Commercial at \@ Left bracket \[ Backslash \\
|
||||
%% Right bracket \] Circumflex \^ Underscore \_
|
||||
%% Grave accent \` Left brace \{ Vertical bar \|
|
||||
%% Right brace \} Tilde \~}
|
||||
\documentclass[a4paper]{article}
|
||||
|
||||
\usepackage[style=long,cols=3]{glossary}[2006/07/20]
|
||||
|
||||
\renewcommand{\glossaryalignment}{llll}
|
||||
|
||||
\newcommand{\glossaryheader}{%
|
||||
\bfseries Name & \bfseries Description & \bfseries Unit &
|
||||
\bfseries Page}
|
||||
|
||||
\makeglossary
|
||||
|
||||
\storeglosentry{w}{name={$w$},sort=w,description={width&m}}
|
||||
\storeglosentry{M}{name={$M$},sort=M,description={mass&kg}}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\printglossary
|
||||
|
||||
The width, \gls{w}, is measured in meters. The mass, \gls{M} is
|
||||
measured in kilograms.
|
||||
|
||||
\end{document}
|
||||
\endinput
|
||||
%%
|
||||
%% End of file `sample4col.tex'.
|
74
docs/ProgrammingCryptol/utils/glossary/sampleAcr.tex
Normal file
74
docs/ProgrammingCryptol/utils/glossary/sampleAcr.tex
Normal file
@ -0,0 +1,74 @@
|
||||
%%
|
||||
%% This is file `sampleAcr.tex',
|
||||
%% generated with the docstrip utility.
|
||||
%%
|
||||
%% The original source files were:
|
||||
%%
|
||||
%% glossary.dtx (with options: `sampleAcr.tex,package')
|
||||
%% Copyright (C) 2006 Nicola Talbot, all rights reserved.
|
||||
%% If you modify this file, you must change its name first.
|
||||
%% You are NOT ALLOWED to distribute this file alone. You are NOT
|
||||
%% ALLOWED to take money for the distribution or use of either this
|
||||
%% file or a changed version, except for a nominal charge for copying
|
||||
%% etc.
|
||||
%% \CharacterTable
|
||||
%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
|
||||
%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
|
||||
%% Digits \0\1\2\3\4\5\6\7\8\9
|
||||
%% Exclamation \! Double quote \" Hash (number) \#
|
||||
%% Dollar \$ Percent \% Ampersand \&
|
||||
%% Acute accent \' Left paren \( Right paren \)
|
||||
%% Asterisk \* Plus \+ Comma \,
|
||||
%% Minus \- Point \. Solidus \/
|
||||
%% Colon \: Semicolon \; Less than \<
|
||||
%% Equals \= Greater than \> Question mark \?
|
||||
%% Commercial at \@ Left bracket \[ Backslash \\
|
||||
%% Right bracket \] Circumflex \^ Underscore \_
|
||||
%% Grave accent \` Left brace \{ Vertical bar \|
|
||||
%% Right brace \} Tilde \~}
|
||||
\documentclass[a4paper]{report}
|
||||
|
||||
\usepackage[colorlinks,plainpages=false]{hyperref}
|
||||
\usepackage[style=altlist,hypertoc,acronym]{glossary}
|
||||
|
||||
\makeacronym
|
||||
|
||||
\newacronym{svm}{support vector machine}{%
|
||||
description=Statistical pattern recognition
|
||||
technique~\cite{svm}}
|
||||
|
||||
\newacronym[ksvm]{k-svm}{kernel support vector machine}{%
|
||||
description={Statistical pattern recognition technique
|
||||
using the ``kernel trick'' (see also SVM)}}
|
||||
|
||||
\begin{document}
|
||||
\tableofcontents
|
||||
|
||||
\chapter{Support Vector Machines}
|
||||
|
||||
The \svm\ is used widely in the area of pattern recognition.
|
||||
\useacronym*[s]{svm} are \ldots
|
||||
|
||||
This is the long version: \svmlong\ or alternatively:
|
||||
\acrln*{svm}.
|
||||
Abbreviation: \svmshort\ or \acrsh*{svm}.
|
||||
|
||||
\chapter{Kernel Support Vector Machines}
|
||||
|
||||
The \ksvm\ is \ifacronymfirstuse{svm}{a}{an} \svm\ that uses
|
||||
the so called ``kernel trick''.
|
||||
|
||||
\resetallacronyms
|
||||
\useacronym*[s]{ksvm} \ldots
|
||||
\svm.
|
||||
|
||||
\begin{thebibliography}{1}
|
||||
\bibitem{svm} \ldots
|
||||
\end{thebibliography}
|
||||
|
||||
\printacronym
|
||||
|
||||
\end{document}
|
||||
\endinput
|
||||
%%
|
||||
%% End of file `sampleAcr.tex'.
|
266
docs/ProgrammingCryptol/utils/glossary/sampleEq.tex
Normal file
266
docs/ProgrammingCryptol/utils/glossary/sampleEq.tex
Normal file
@ -0,0 +1,266 @@
|
||||
%%
|
||||
%% This is file `sampleEq.tex',
|
||||
%% generated with the docstrip utility.
|
||||
%%
|
||||
%% The original source files were:
|
||||
%%
|
||||
%% glossary.dtx (with options: `sampleEq.tex,package')
|
||||
%% Copyright (C) 2006 Nicola Talbot, all rights reserved.
|
||||
%% If you modify this file, you must change its name first.
|
||||
%% You are NOT ALLOWED to distribute this file alone. You are NOT
|
||||
%% ALLOWED to take money for the distribution or use of either this
|
||||
%% file or a changed version, except for a nominal charge for copying
|
||||
%% etc.
|
||||
%% \CharacterTable
|
||||
%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
|
||||
%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
|
||||
%% Digits \0\1\2\3\4\5\6\7\8\9
|
||||
%% Exclamation \! Double quote \" Hash (number) \#
|
||||
%% Dollar \$ Percent \% Ampersand \&
|
||||
%% Acute accent \' Left paren \( Right paren \)
|
||||
%% Asterisk \* Plus \+ Comma \,
|
||||
%% Minus \- Point \. Solidus \/
|
||||
%% Colon \: Semicolon \; Less than \<
|
||||
%% Equals \= Greater than \> Question mark \?
|
||||
%% Commercial at \@ Left bracket \[ Backslash \\
|
||||
%% Right bracket \] Circumflex \^ Underscore \_
|
||||
%% Grave accent \` Left brace \{ Vertical bar \|
|
||||
%% Right brace \} Tilde \~}
|
||||
\documentclass[a4paper,12pt]{report}
|
||||
|
||||
\usepackage{amsmath}
|
||||
\usepackage[colorlinks]{hyperref}
|
||||
\usepackage[header,border=none,cols=3,number=equation]{glossary}[2006/07/20]
|
||||
|
||||
\newcommand{\erf}{\operatorname{erf}}
|
||||
\newcommand{\erfc}{\operatorname{erfc}}
|
||||
|
||||
\makeglossary
|
||||
|
||||
|
||||
|
||||
\renewcommand{\glossaryname}{Index of Special Functions
|
||||
and Notations}
|
||||
|
||||
|
||||
\renewcommand{\entryname}{Notation}
|
||||
|
||||
\renewcommand{\descriptionname}{Function Name}
|
||||
|
||||
\renewcommand{\glspageheader}{Number of Formula}
|
||||
|
||||
\newcommand{\glossarysubheader}{ & & \\}
|
||||
|
||||
|
||||
\storeglosentry{Gamma}{name=\ensuremath{\Gamma(z)},
|
||||
description=Gamma function,sort=Gamma}
|
||||
|
||||
\storeglosentry{gamma}{name={\ensuremath{\gamma(\alpha,x)}},
|
||||
description=Incomplete gamma function,sort=gamma}
|
||||
|
||||
\storeglosentry{iGamma}{name={\ensuremath{\Gamma(\alpha,x)}},
|
||||
description=Incomplete gamma function,sort=Gamma}
|
||||
|
||||
\storeglosentry{psi}{name=\ensuremath{\psi(x)},
|
||||
description=Psi function,sort=psi}
|
||||
|
||||
\storeglosentry{erf}{name=\ensuremath{\erf(x)},
|
||||
description=Error function,sort=erf}
|
||||
|
||||
\storeglosentry{erfc}{name=\ensuremath{\erfc},
|
||||
description=Complementary error function,sort=erfc}
|
||||
|
||||
\storeglosentry{B}{name={\ensuremath{B(x,y)}},
|
||||
description=Beta function,sort=B}
|
||||
|
||||
\storeglosentry{Bx}{name={\ensuremath{B_x(p,q)}},
|
||||
description=Incomplete beta function,sort=Bx}
|
||||
|
||||
\storeglosentry{Tn}{name=\ensuremath{T_n(x)},
|
||||
description=Chebyshev's polynomials of the first kind,sort=Tn}
|
||||
|
||||
\storeglosentry{Un}{name=\ensuremath{U_n(x)},
|
||||
description=Chebyshev's polynomials of the second kind,sort=Un}
|
||||
|
||||
\storeglosentry{Hn}{name=\ensuremath{H_n(x)},
|
||||
description=Hermite polynomials,sort=Hn}
|
||||
|
||||
\storeglosentry{Ln}{name=\ensuremath{L_n^\alpha(x)},
|
||||
description=Laguerre polynomials,sort=Lna}
|
||||
|
||||
\storeglosentry{Znu}{name=\ensuremath{Z_\nu(z)},
|
||||
description=Bessel functions,sort=Z}
|
||||
|
||||
\storeglosentry{Phi}{name={\ensuremath{\Phi(\alpha,\gamma;z)}},
|
||||
description=confluent hypergeometric function,sort=Pagz}
|
||||
|
||||
\storeglosentry{knu}{name=\ensuremath{k_\nu(x)},
|
||||
description=Bateman's function,sort=kv}
|
||||
|
||||
\storeglosentry{Dp}{name=\ensuremath{D_p(z)},
|
||||
description=Parabolic cylinder functions,sort=Dp}
|
||||
|
||||
\storeglosentry{F}{name={\ensuremath{F(\phi,k)}},
|
||||
description=Elliptical integral of the first kind,sort=Fpk}
|
||||
|
||||
\storeglosentry{C}{name=\ensuremath{C},
|
||||
description=Euler's constant,sort=C}
|
||||
|
||||
\storeglosentry{G}{name=\ensuremath{G},
|
||||
description=Catalan's constant,sort=G}
|
||||
|
||||
\begin{document}
|
||||
\title{A Sample Document Using glossary.sty}
|
||||
\author{Nicola Talbot}
|
||||
\maketitle
|
||||
|
||||
\begin{abstract}
|
||||
This is a sample document illustrating the use of the \textsf{glossary}
|
||||
package. The functions here have been taken from ``Tables of
|
||||
Integrals, Series, and Products'' by I.S.~Gradshteyn and I.M~Ryzhik.
|
||||
The glossary is a list of special functions, so
|
||||
the equation number has been used rather than the page number. This
|
||||
can be done using the \texttt{number=equation} package
|
||||
option.
|
||||
\end{abstract}
|
||||
|
||||
\printglossary
|
||||
|
||||
\chapter{Gamma Functions}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Gamma} = \int_{0}^{\infty}e^{-t}t^{z-1}\,dt
|
||||
\end{equation}
|
||||
|
||||
\verb|\ensuremath| is only required here if using
|
||||
hyperlinks.
|
||||
\begin{equation}
|
||||
\useGlosentry{Gamma}{\ensuremath{\Gamma(x+1)}} = x\Gamma(x)
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{gamma} = \int_0^x e^{-t}t^{\alpha-1}\,dt
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{iGamma} = \int_x^\infty e^{-t}t^{\alpha-1}\,dt
|
||||
\end{equation}
|
||||
|
||||
\newpage
|
||||
|
||||
\begin{equation}
|
||||
\gls{Gamma} = \Gamma(\alpha, x) + \gamma(\alpha, x)
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{psi} = \frac{d}{dx}\ln\Gamma(x)
|
||||
\end{equation}
|
||||
|
||||
\chapter{Error Functions}
|
||||
|
||||
\begin{equation}
|
||||
\gls{erf} = \frac{2}{\surd\pi}\int_0^x e^{-t^2}\,dt
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{erfc} = 1 - \erf(x)
|
||||
\end{equation}
|
||||
|
||||
\chapter{Beta Function}
|
||||
|
||||
\begin{equation}
|
||||
\gls{B} = 2\int_0^1 t^{x-1}(1-t^2)^{y-1}\,dt
|
||||
\end{equation}
|
||||
Alternatively:
|
||||
\begin{equation}
|
||||
\gls{B} = 2\int_0^{\frac\pi2}\sin^{2x-1}\phi\cos^{2y-1}\phi\,d\phi
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{B} = \frac{\Gamma(x)\Gamma(y)}{\Gamma(x+y)} = B(y,x)
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Bx} = \int_0^x t^{p-1}(1-t)^{q-1}\,dt
|
||||
\end{equation}
|
||||
|
||||
\chapter{Polynomials}
|
||||
|
||||
\section{Chebyshev's polynomials}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Tn} = \cos(n\arccos x)
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Un} = \frac{\sin[(n+1)\arccos x]}{\sin[\arccos x]}
|
||||
\end{equation}
|
||||
|
||||
\section{Hermite polynomials}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Hn} = (-1)^n e^{x^2} \frac{d^n}{dx^n}(e^{-x^2})
|
||||
\end{equation}
|
||||
|
||||
\section{Laguerre polynomials}
|
||||
|
||||
\begin{equation}
|
||||
L_n^{\alpha} (x) = \frac{1}{n!}e^x x^{-\alpha}
|
||||
\frac{d^n}{dx^n}(e^{-x}x^{n+\alpha})
|
||||
\end{equation}
|
||||
|
||||
\chapter{Bessel Functions}
|
||||
|
||||
Bessel functions $Z_\nu$ are solutions of
|
||||
\begin{equation}
|
||||
\useglosentry{Znu}
|
||||
\frac{d^2Z_\nu}{dz^2} + \frac{1}{z}\,\frac{dZ_\nu}{dz} +
|
||||
\left( 1-\frac{\nu^2}{z^2}Z_\nu = 0 \right)
|
||||
\end{equation}
|
||||
|
||||
\chapter{Confluent hypergeometric function}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Phi} = 1 + \frac{\alpha}{\gamma}\,\frac{z}{1!}
|
||||
+ \frac{\alpha(\alpha+1)}{\gamma(\gamma+1)}\,\frac{z^2}{2!}
|
||||
+\frac{\alpha(\alpha+1)(\alpha+2)}{\gamma(\gamma+1)(\gamma+2)}\,
|
||||
\frac{z^3}{3!} + \cdots
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{knu} = \frac{2}{\pi}\int_0^{\pi/2}
|
||||
\cos(x \tan\theta - \nu\theta)\,d\theta
|
||||
\end{equation}
|
||||
|
||||
\chapter{Parabolic cylinder functions}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Dp} = 2^{\frac{p}{2}}e^{-\frac{z^2}{4}}
|
||||
\left\{
|
||||
\frac{\surd\pi}{\Gamma\left(\frac{1-p}{2}\right)}
|
||||
\Phi\left(-\frac{p}{2},\frac{1}{2};\frac{z^2}{2}\right)
|
||||
-\frac{\sqrt{2\pi}z}{\Gamma\left(-\frac{p}{2}\right)}
|
||||
\Phi\left(\frac{1-p}{2},\frac{3}{2};\frac{z^2}{2}\right)
|
||||
\right\}
|
||||
\end{equation}
|
||||
|
||||
\chapter{Elliptical Integral of the First Kind}
|
||||
|
||||
\begin{equation}
|
||||
\gls{F} = \int_0^\phi \frac{d\alpha}{\sqrt{1-k^2\sin^2\alpha}}
|
||||
\end{equation}
|
||||
|
||||
\chapter{Constants}
|
||||
|
||||
\begin{equation}
|
||||
\gls{C} = 0.577\,215\,664\,901\ldots
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{G} = 0.915\,965\,594\ldots
|
||||
\end{equation}
|
||||
|
||||
\end{document}
|
||||
\endinput
|
||||
%%
|
||||
%% End of file `sampleEq.tex'.
|
290
docs/ProgrammingCryptol/utils/glossary/sampleEqPg.tex
Normal file
290
docs/ProgrammingCryptol/utils/glossary/sampleEqPg.tex
Normal file
@ -0,0 +1,290 @@
|
||||
%%
|
||||
%% This is file `sampleEqPg.tex',
|
||||
%% generated with the docstrip utility.
|
||||
%%
|
||||
%% The original source files were:
|
||||
%%
|
||||
%% glossary.dtx (with options: `sampleEqPg.tex,package')
|
||||
%% Copyright (C) 2006 Nicola Talbot, all rights reserved.
|
||||
%% If you modify this file, you must change its name first.
|
||||
%% You are NOT ALLOWED to distribute this file alone. You are NOT
|
||||
%% ALLOWED to take money for the distribution or use of either this
|
||||
%% file or a changed version, except for a nominal charge for copying
|
||||
%% etc.
|
||||
%% \CharacterTable
|
||||
%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
|
||||
%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
|
||||
%% Digits \0\1\2\3\4\5\6\7\8\9
|
||||
%% Exclamation \! Double quote \" Hash (number) \#
|
||||
%% Dollar \$ Percent \% Ampersand \&
|
||||
%% Acute accent \' Left paren \( Right paren \)
|
||||
%% Asterisk \* Plus \+ Comma \,
|
||||
%% Minus \- Point \. Solidus \/
|
||||
%% Colon \: Semicolon \; Less than \<
|
||||
%% Equals \= Greater than \> Question mark \?
|
||||
%% Commercial at \@ Left bracket \[ Backslash \\
|
||||
%% Right bracket \] Circumflex \^ Underscore \_
|
||||
%% Grave accent \` Left brace \{ Vertical bar \|
|
||||
%% Right brace \} Tilde \~}
|
||||
\documentclass[a4paper,12pt]{report}
|
||||
|
||||
\usepackage{amsmath}
|
||||
\usepackage[colorlinks]{hyperref}
|
||||
\usepackage[header,toc,border=none,cols=3,
|
||||
number=equation]{glossary}[2006/07/20]
|
||||
|
||||
\newcommand{\erf}{\operatorname{erf}}
|
||||
\newcommand{\erfc}{\operatorname{erfc}}
|
||||
|
||||
\renewcommand{\glossaryname}{Index of Special Functions and Notations}
|
||||
|
||||
\renewcommand{\glossarypreamble}{Numbers in italic indicate the equation number,
|
||||
numbers in bold indicate page numbers where the main definition occurs.\par}
|
||||
|
||||
\setglossary{glsnumformat=hyperit}
|
||||
|
||||
\renewcommand{\entryname}{Notation}
|
||||
|
||||
\renewcommand{\descriptionname}{Function Name}
|
||||
|
||||
\newcommand{\glossarysubheader}{ & & \\}
|
||||
|
||||
|
||||
\storeglosentry{Gamma}{name=\ensuremath{\Gamma(z)},
|
||||
description=Gamma function,sort=Gamma}
|
||||
|
||||
\storeglosentry{gamma}{name=\ensuremath{\gamma(\alpha,x)},
|
||||
description=Incomplete gamma function,sort=gamma}
|
||||
|
||||
\storeglosentry{iGamma}{name=\ensuremath{\Gamma(\alpha,x)},
|
||||
description=Incomplete gamma function,sort=Gamma}
|
||||
|
||||
\storeglosentry{psi}{name=\ensuremath{\psi(x)},
|
||||
description=Psi function,sort=psi}
|
||||
|
||||
\storeglosentry{erf}{name=\ensuremath{\erf(x)},
|
||||
description=Error function,sort=erf}
|
||||
|
||||
\storeglosentry{erfc}{name=\ensuremath{\erfc(x)},
|
||||
description=Complementary error function,sort=erfc}
|
||||
|
||||
\storeglosentry{beta}{name=\ensuremath{B(x,y)},
|
||||
description=Beta function,sort=B}
|
||||
|
||||
\storeglosentry{Bx}{name=\ensuremath{B_x(p,q)},
|
||||
description=Incomplete beta function,sort=Bx}
|
||||
|
||||
\storeglosentry{Tn}{name=\ensuremath{T_n(x)},
|
||||
description=Chebyshev's polynomials of the first kind,
|
||||
sort=Tn}
|
||||
|
||||
\storeglosentry{Un}{name=\ensuremath{U_n(x)},
|
||||
description=Chebyshev's polynomials of the second kind,
|
||||
sort=Un}
|
||||
|
||||
\storeglosentry{Hn}{name=\ensuremath{H_n(x)},
|
||||
description=Hermite polynomials,sort=Hn}
|
||||
|
||||
\storeglosentry{Lna}{name=\ensuremath{L_n^\alpha(x)},
|
||||
description=Laguerre polynomials,sort=Lna}
|
||||
|
||||
\storeglosentry{Znu}{name=\ensuremath{Z_\nu(z)},
|
||||
description=Bessel functions,sort=Z}
|
||||
|
||||
\storeglosentry{Pagz}{name=\ensuremath{\Phi(\alpha,\gamma;z)},
|
||||
description=confluent hypergeometric function,sort=Pagz}
|
||||
|
||||
\storeglosentry{kv}{name=\ensuremath{k_\nu(x)},
|
||||
description=Bateman's function,sort=kv}
|
||||
|
||||
\storeglosentry{Dp}{name=\ensuremath{D_p(z)},
|
||||
description=Parabolic cylinder functions,sort=Dp}
|
||||
|
||||
\storeglosentry{Fpk}{name=\ensuremath{F(\phi,k)},
|
||||
description=Elliptical integral of the first kind,sort=Fpk}
|
||||
|
||||
\storeglosentry{C}{name=\ensuremath{C},
|
||||
description=Euler's constant,sort=C}
|
||||
|
||||
\storeglosentry{G}{name=\ensuremath{G},
|
||||
description=Catalan's constant,sort=G}
|
||||
|
||||
\renewcommand{\shortglossaryname}{Special Functions}
|
||||
|
||||
\makeglossary
|
||||
|
||||
\pagestyle{headings}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\title{Sample Document Using Interchangable Numbering}
|
||||
\author{Nicola Talbot}
|
||||
\maketitle
|
||||
|
||||
\begin{abstract}
|
||||
This is a sample document illustrating the use of the \textsf{glossary}
|
||||
package. The functions here have been taken from ``Tables of
|
||||
Integrals, Series, and Products'' by I.S.~Gradshteyn and I.M~Ryzhik.
|
||||
|
||||
The glossary lists both page numbers and equation numbers.
|
||||
Since the majority of the entries use the equation number,
|
||||
\texttt{number=equation} was used as a package option.
|
||||
The entries that should refer to the page number instead
|
||||
use the \texttt{number=equation} glossary key.
|
||||
Note that this example will only work where the
|
||||
page number and equation number compositor is the same. So
|
||||
it won't work if, say, the page numbers are of the form
|
||||
2-4 and the equation numbers are of the form 4.6.
|
||||
As most of the glossary entries should have an italic
|
||||
format, it is easiest to set the default format to
|
||||
italic.
|
||||
|
||||
\end{abstract}
|
||||
|
||||
\tableofcontents
|
||||
|
||||
\printglossary
|
||||
|
||||
\chapter{Gamma Functions}
|
||||
|
||||
The \useGlosentry[number=page,format=hyperbf]{Gamma}{gamma function} is
|
||||
defined as
|
||||
\begin{equation}
|
||||
\gls{Gamma} = \int_{0}^{\infty}e^{-t}t^{z-1}\,dt
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\useGlosentry{Gamma}{\ensuremath{\Gamma(x+1)}} = x\Gamma(x)
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{gamma} = \int_0^x e^{-t}t^{\alpha-1}\,dt
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{iGamma} = \int_x^\infty e^{-t}t^{\alpha-1}\,dt
|
||||
\end{equation}
|
||||
|
||||
\newpage
|
||||
|
||||
\begin{equation}
|
||||
\useGlosentry{Gamma}{\ensuremath{\Gamma(\alpha)}} = \Gamma(\alpha, x) + \gamma(\alpha, x)
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{psi} = \frac{d}{dx}\ln\Gamma(x)
|
||||
\end{equation}
|
||||
|
||||
\chapter{Error Functions}
|
||||
|
||||
The \useGlosentry[number=page,format=hyperbf]{erf}{error
|
||||
function} is defined as:
|
||||
\begin{equation}
|
||||
\gls{erf} = \frac{2}{\surd\pi}\int_0^x e^{-t^2}\,dt
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{erfc} = 1 - \erf(x)
|
||||
\end{equation}
|
||||
|
||||
\chapter{Beta Function}
|
||||
|
||||
\begin{equation}
|
||||
\gls{beta} = 2\int_0^1 t^{x-1}(1-t^2)^{y-1}\,dt
|
||||
\end{equation}
|
||||
Alternatively:
|
||||
\begin{equation}
|
||||
\gls{beta} = 2\int_0^{\frac\pi2}\sin^{2x-1}\phi\cos^{2y-1}\phi\,d\phi
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{beta} = \frac{\Gamma(x)\Gamma(y)}{\Gamma(x+y)} = B(y,x)
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Bx} = \int_0^x t^{p-1}(1-t)^{q-1}\,dt
|
||||
\end{equation}
|
||||
|
||||
\chapter{Chebyshev's polynomials}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Tn} = \cos(n\arccos x)
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Un} = \frac{\sin[(n+1)\arccos x]}{\sin[\arccos x]}
|
||||
\end{equation}
|
||||
|
||||
\chapter{Hermite polynomials}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Hn} = (-1)^n e^{x^2} \frac{d^n}{dx^n}(e^{-x^2})
|
||||
\end{equation}
|
||||
|
||||
\chapter{Laguerre polynomials}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Lna} = \frac{1}{n!}e^x x^{-\alpha}
|
||||
\frac{d^n}{dx^n}(e^{-x}x^{n+\alpha})
|
||||
\end{equation}
|
||||
|
||||
\chapter{Bessel Functions}
|
||||
|
||||
Bessel functions $Z_\nu(z)$ are solutions of
|
||||
\begin{equation}
|
||||
\frac{d^2Z_\nu}{dz^2} + \frac{1}{z}\,\frac{dZ_\nu}{dz} +
|
||||
\left(
|
||||
1-\frac{\nu^2}{z^2}Z_\nu = 0
|
||||
\right)
|
||||
\end{equation}
|
||||
\useglosentry{Znu}
|
||||
|
||||
\chapter{Confluent hypergeometric function}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Pagz} = 1 + \frac{\alpha}{\gamma}\,\frac{z}{1!}
|
||||
+ \frac{\alpha(\alpha+1)}{\gamma(\gamma+1)}\,\frac{z^2}{2!}
|
||||
+\frac{\alpha(\alpha+1)(\alpha+2)}
|
||||
{\gamma(\gamma+1)(\gamma+2)}
|
||||
\,\frac{z^3}{3!}
|
||||
+ \cdots
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{kv} = \frac{2}{\pi}\int_0^{\pi/2}
|
||||
\cos(x \tan\theta - \nu\theta)\,d\theta
|
||||
\end{equation}
|
||||
|
||||
\chapter{Parabolic cylinder functions}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Dp} = 2^{\frac{p}{2}}e^{-\frac{z^2}{4}}
|
||||
\left\{
|
||||
\frac{\surd\pi}{\Gamma\left(\frac{1-p}{2}\right)}
|
||||
\Phi\left(-\frac{p}{2},\frac{1}{2};\frac{z^2}{2}\right)
|
||||
-\frac{\sqrt{2\pi}z}{\Gamma\left(-\frac{p}{2}\right)}
|
||||
\Phi\left(\frac{1-p}{2},\frac{3}{2};\frac{z^2}{2}\right)
|
||||
\right\}
|
||||
\end{equation}
|
||||
|
||||
\chapter{Elliptical Integral of the First Kind}
|
||||
|
||||
\begin{equation}
|
||||
\gls{Fpk} = \int_0^\phi
|
||||
\frac{d\alpha}{\sqrt{1-k^2\sin^2\alpha}}
|
||||
\end{equation}
|
||||
|
||||
\chapter{Constants}
|
||||
|
||||
\begin{equation}
|
||||
\gls{C} = 0.577\,215\,664\,901\ldots
|
||||
\end{equation}
|
||||
|
||||
\begin{equation}
|
||||
\gls{G} = 0.915\,965\,594\ldots
|
||||
\end{equation}
|
||||
|
||||
\end{document}
|
||||
\endinput
|
||||
%%
|
||||
%% End of file `sampleEqPg.tex'.
|
94
docs/ProgrammingCryptol/utils/glossary/sampleNtn.tex
Normal file
94
docs/ProgrammingCryptol/utils/glossary/sampleNtn.tex
Normal file
@ -0,0 +1,94 @@
|
||||
%%
|
||||
%% This is file `sampleNtn.tex',
|
||||
%% generated with the docstrip utility.
|
||||
%%
|
||||
%% The original source files were:
|
||||
%%
|
||||
%% glossary.dtx (with options: `sampleNtn.tex,package')
|
||||
%% Copyright (C) 2006 Nicola Talbot, all rights reserved.
|
||||
%% If you modify this file, you must change its name first.
|
||||
%% You are NOT ALLOWED to distribute this file alone. You are NOT
|
||||
%% ALLOWED to take money for the distribution or use of either this
|
||||
%% file or a changed version, except for a nominal charge for copying
|
||||
%% etc.
|
||||
%% \CharacterTable
|
||||
%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
|
||||
%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
|
||||
%% Digits \0\1\2\3\4\5\6\7\8\9
|
||||
%% Exclamation \! Double quote \" Hash (number) \#
|
||||
%% Dollar \$ Percent \% Ampersand \&
|
||||
%% Acute accent \' Left paren \( Right paren \)
|
||||
%% Asterisk \* Plus \+ Comma \,
|
||||
%% Minus \- Point \. Solidus \/
|
||||
%% Colon \: Semicolon \; Less than \<
|
||||
%% Equals \= Greater than \> Question mark \?
|
||||
%% Commercial at \@ Left bracket \[ Backslash \\
|
||||
%% Right bracket \] Circumflex \^ Underscore \_
|
||||
%% Grave accent \` Left brace \{ Vertical bar \|
|
||||
%% Right brace \} Tilde \~}
|
||||
\documentclass{report}
|
||||
|
||||
\usepackage[plainpages=false,colorlinks]{hyperref}
|
||||
\usepackage{html}
|
||||
\usepackage[toc,style=long,cols=3]{glossary}
|
||||
|
||||
\makeglossary
|
||||
|
||||
\newglossarytype{notation}{not}{ntn}[style=long,cols=2,border,header]
|
||||
|
||||
\newcommand{\notationname}{Notation}
|
||||
\setglossary{type=notation,glsnumformat=ignore,glodelim={.}}
|
||||
|
||||
\makenotation
|
||||
|
||||
\begin{document}
|
||||
|
||||
\title{Sample Document using glossary Package}
|
||||
\author{Nicola Talbot}
|
||||
\pagenumbering{alph}
|
||||
\maketitle
|
||||
|
||||
\begin{abstract}
|
||||
\pagenumbering{Alph}
|
||||
This is a sample document illustrating the use of the
|
||||
\textsf{glossary} package. In this example, a new glossary type
|
||||
called \texttt{notation} is defined, so that the document can have a
|
||||
separate glossary of terms and index of notation. The index of notation
|
||||
doesn't have associated numbers.
|
||||
\end{abstract}
|
||||
|
||||
\pagenumbering{roman}
|
||||
\tableofcontents
|
||||
|
||||
\printglossary
|
||||
|
||||
|
||||
\printglossary[notation]
|
||||
|
||||
\chapter{Introduction}
|
||||
\pagenumbering{arabic}
|
||||
|
||||
Sets\glossary{name=set,description=A collection of distinct objects}
|
||||
are denoted by a caligraphic font
|
||||
e.g.\ $\mathcal{S}$%
|
||||
\notation{name=$\mathcal{S}$,description=A set,sort=S}.
|
||||
|
||||
Let $\mathcal{U}$ denote the universal set\notation{
|
||||
name=$\mathcal{U}$,description={The universal set},sort=U}.
|
||||
|
||||
The cardinality\glossary{name=cardinality,
|
||||
description=The number of elements in the specified set} of
|
||||
a set $\mathcal{S}$ is denoted $|\mathcal{S}|$%
|
||||
\notation{name=$\mid\mathcal{S}\mid$,
|
||||
description=cardinality of $\mathcal{S}$,sort=cardinality}
|
||||
|
||||
\chapter{Next}
|
||||
|
||||
Now for a hyperlink:
|
||||
\xnotation{name=$\mathcal{U}$, description={The universal
|
||||
set}, sort=U}{$\mathcal{U}$}.
|
||||
|
||||
\end{document}
|
||||
\endinput
|
||||
%%
|
||||
%% End of file `sampleNtn.tex'.
|
102
docs/ProgrammingCryptol/utils/glossary/sampleNtn2.tex
Normal file
102
docs/ProgrammingCryptol/utils/glossary/sampleNtn2.tex
Normal file
@ -0,0 +1,102 @@
|
||||
%%
|
||||
%% This is file `sampleNtn2.tex',
|
||||
%% generated with the docstrip utility.
|
||||
%%
|
||||
%% The original source files were:
|
||||
%%
|
||||
%% glossary.dtx (with options: `sampleNtn2.tex,package')
|
||||
%% Copyright (C) 2006 Nicola Talbot, all rights reserved.
|
||||
%% If you modify this file, you must change its name first.
|
||||
%% You are NOT ALLOWED to distribute this file alone. You are NOT
|
||||
%% ALLOWED to take money for the distribution or use of either this
|
||||
%% file or a changed version, except for a nominal charge for copying
|
||||
%% etc.
|
||||
%% \CharacterTable
|
||||
%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
|
||||
%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
|
||||
%% Digits \0\1\2\3\4\5\6\7\8\9
|
||||
%% Exclamation \! Double quote \" Hash (number) \#
|
||||
%% Dollar \$ Percent \% Ampersand \&
|
||||
%% Acute accent \' Left paren \( Right paren \)
|
||||
%% Asterisk \* Plus \+ Comma \,
|
||||
%% Minus \- Point \. Solidus \/
|
||||
%% Colon \: Semicolon \; Less than \<
|
||||
%% Equals \= Greater than \> Question mark \?
|
||||
%% Commercial at \@ Left bracket \[ Backslash \\
|
||||
%% Right bracket \] Circumflex \^ Underscore \_
|
||||
%% Grave accent \` Left brace \{ Vertical bar \|
|
||||
%% Right brace \} Tilde \~}
|
||||
\documentclass{report}
|
||||
|
||||
\usepackage[plainpages=false,colorlinks]{hyperref}
|
||||
\usepackage{html}
|
||||
\usepackage[toc]{glossary}[2006/07/20]
|
||||
|
||||
\makeglossary
|
||||
|
||||
\newglossarytype[nlg]{notation}{not}{ntn}[number=none]
|
||||
|
||||
\newcommand{\notationname}{Notation}
|
||||
|
||||
\makenotation
|
||||
|
||||
\begin{document}
|
||||
|
||||
\storeglosentry[notation]{not:set}{name={$\mathcal{S}$},
|
||||
description=A set,sort=S}
|
||||
|
||||
\storeglosentry[notation]{not:U}{name=$\mathcal{U}$,
|
||||
description={The universal set},sort=U}
|
||||
|
||||
\storeglosentry[notation]{not:card}{name=$\mid\mathcal{S}\mid$,
|
||||
description=cardinality of $\mathcal{S}$,
|
||||
sort=cardinality}
|
||||
|
||||
\storeglosentry{glos:set}{name=set,description=A collection of
|
||||
distinct objects}
|
||||
|
||||
\storeglosentry{glos:card}{name=cardinality,description=The number of
|
||||
elements in the specified set}
|
||||
|
||||
\title{Sample Document using glossary Package}
|
||||
\author{Nicola Talbot}
|
||||
\pagenumbering{alph}
|
||||
\maketitle
|
||||
|
||||
\begin{abstract}
|
||||
\pagenumbering{Alph}
|
||||
This is a sample document illustrating the use of the
|
||||
\textsf{glossary} package. In this example, a new glossary type
|
||||
called \texttt{notation} is defined, so that the document can have a
|
||||
separate glossary of terms and index of notation. The index of notation
|
||||
doesn't have associated numbers.
|
||||
\end{abstract}
|
||||
|
||||
\pagenumbering{roman}
|
||||
\tableofcontents
|
||||
|
||||
\printglossary
|
||||
|
||||
|
||||
\printnotation
|
||||
|
||||
\chapter{Introduction}
|
||||
\pagenumbering{arabic}
|
||||
|
||||
Sets\useglosentry{glos:set}
|
||||
are denoted by a caligraphic font
|
||||
e.g.\ $\mathcal{S}$\useglosentry{not:set}.
|
||||
|
||||
Let \gls{not:U} denote the universal set.
|
||||
|
||||
The \gls{glos:card} of a set $\mathcal{S}$ is denoted
|
||||
\gls{not:card}.
|
||||
|
||||
\chapter{Another Chapter}
|
||||
|
||||
Another mention of the universal set \gls{not:U}.
|
||||
|
||||
\end{document}
|
||||
\endinput
|
||||
%%
|
||||
%% End of file `sampleNtn2.tex'.
|
81
docs/ProgrammingCryptol/utils/glossary/sampleSec.tex
Normal file
81
docs/ProgrammingCryptol/utils/glossary/sampleSec.tex
Normal file
@ -0,0 +1,81 @@
|
||||
%%
|
||||
%% This is file `sampleSec.tex',
|
||||
%% generated with the docstrip utility.
|
||||
%%
|
||||
%% The original source files were:
|
||||
%%
|
||||
%% glossary.dtx (with options: `sampleSec.tex,package')
|
||||
%% Copyright (C) 2006 Nicola Talbot, all rights reserved.
|
||||
%% If you modify this file, you must change its name first.
|
||||
%% You are NOT ALLOWED to distribute this file alone. You are NOT
|
||||
%% ALLOWED to take money for the distribution or use of either this
|
||||
%% file or a changed version, except for a nominal charge for copying
|
||||
%% etc.
|
||||
%% \CharacterTable
|
||||
%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
|
||||
%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
|
||||
%% Digits \0\1\2\3\4\5\6\7\8\9
|
||||
%% Exclamation \! Double quote \" Hash (number) \#
|
||||
%% Dollar \$ Percent \% Ampersand \&
|
||||
%% Acute accent \' Left paren \( Right paren \)
|
||||
%% Asterisk \* Plus \+ Comma \,
|
||||
%% Minus \- Point \. Solidus \/
|
||||
%% Colon \: Semicolon \; Less than \<
|
||||
%% Equals \= Greater than \> Question mark \?
|
||||
%% Commercial at \@ Left bracket \[ Backslash \\
|
||||
%% Right bracket \] Circumflex \^ Underscore \_
|
||||
%% Grave accent \` Left brace \{ Vertical bar \|
|
||||
%% Right brace \} Tilde \~}
|
||||
\documentclass{report}
|
||||
|
||||
\usepackage[plainpages=false,colorlinks]{hyperref}
|
||||
\usepackage[style=altlist,toc,number=section]{glossary}
|
||||
|
||||
\makeglossary
|
||||
|
||||
\storeglosentry{ident}{name=identity matrix,description=diagonal
|
||||
matrix with 1s along the leading diagonal}
|
||||
|
||||
\storeglosentry{diag}{name=diagonal matrix,
|
||||
description=matrix whose only non-zero entries are along
|
||||
the leading diagonal}
|
||||
|
||||
\storeglosentry{sing}{name=singular matrix,
|
||||
description=matrix with zero determinant}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\pagenumbering{roman}
|
||||
\tableofcontents
|
||||
|
||||
\printglossary
|
||||
|
||||
\chapter{Introduction}
|
||||
\pagenumbering{arabic}
|
||||
This is a sample document illustrating the use of the
|
||||
\textsf{glossary} package.
|
||||
|
||||
\chapter{Diagonal matrices}
|
||||
|
||||
A \gls[format=hyperit]{diag} is a matrix where all elements not on the
|
||||
leading diagonal are zero. This is the
|
||||
primary definition, so an italic font is used for the page number.
|
||||
|
||||
\newpage
|
||||
\section{Identity matrix}
|
||||
The \gls[format=hyperit]{ident} is a \gls{diag} whose leading
|
||||
diagonal elements are all equal to 1.
|
||||
|
||||
Here is another entry for a \gls{diag}.
|
||||
|
||||
\chapter{Singular Matrices}
|
||||
|
||||
A \gls{sing} is a matrix with zero determinant.
|
||||
\useGlosentry{sing}{Singular matrices} are non-invertible.
|
||||
|
||||
Another \gls{ident} entry.
|
||||
|
||||
\end{document}
|
||||
\endinput
|
||||
%%
|
||||
%% End of file `sampleSec.tex'.
|
88
docs/ProgrammingCryptol/utils/trickery.tex
Normal file
88
docs/ProgrammingCryptol/utils/trickery.tex
Normal file
@ -0,0 +1,88 @@
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% The following is copied from book.cls
|
||||
%%% Beware: if the style changes, change this too
|
||||
\makeatletter
|
||||
\renewenvironment{thebibliography}[1]{%
|
||||
\chapter*{\bibname
|
||||
\@mkboth{\MakeUppercase\bibname}{\MakeUppercase\bibname}}%
|
||||
\phantomsection
|
||||
\addcontentsline{toc}{chapter}{Bibliography}
|
||||
(Each entry is followed by a list of page numbers on which
|
||||
the citation appears. All cited URLs, unless otherwise stated, were last accessed in November 2010.)\\
|
||||
\list{\@biblabel{\@arabic\c@enumiv}}%
|
||||
{\settowidth\labelwidth{\@biblabel{#1}}%
|
||||
\leftmargin\labelwidth
|
||||
\advance\leftmargin\labelsep
|
||||
\@openbib@code
|
||||
\usecounter{enumiv}%
|
||||
\let\p@enumiv\@empty
|
||||
\renewcommand\theenumiv{\@arabic\c@enumiv}}%
|
||||
\sloppy
|
||||
\clubpenalty4000
|
||||
\@clubpenalty \clubpenalty
|
||||
\widowpenalty4000%
|
||||
\sfcode`\.\@m}
|
||||
{\def\@noitemerr
|
||||
{\@latex@warning{Empty `thebibliography' environment}}%
|
||||
\endlist}
|
||||
\makeatother
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% index trickery
|
||||
\makeatletter
|
||||
\renewenvironment{theindex}{%
|
||||
\if@twocolumn
|
||||
\@restonecolfalse
|
||||
\else
|
||||
\@restonecoltrue
|
||||
\fi
|
||||
\columnseprule \z@
|
||||
\columnsep 35\p@
|
||||
\twocolumn[\@makeschapterhead{\indexname}
|
||||
\phantomsection
|
||||
\addcontentsline{toc}{chapter}{Index}
|
||||
%\noindent (Some explanations or yet others totally unrelated but still
|
||||
%useful might go here or there. no one cares.)\\
|
||||
]%
|
||||
\@mkboth{\MakeUppercase\indexname}%
|
||||
{\MakeUppercase\indexname}%
|
||||
\parskip\z@ \@plus .3\p@\relax
|
||||
\let\item\@idxitem}
|
||||
{\if@restonecol\onecolumn\else\clearpage\fi}
|
||||
\makeatother
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% toc trickery
|
||||
\makeatletter
|
||||
\renewcommand\tableofcontents{%
|
||||
\if@twocolumn
|
||||
\@restonecoltrue\onecolumn
|
||||
\else
|
||||
\@restonecolfalse
|
||||
\fi
|
||||
\chapter*{\contentsname
|
||||
\@mkboth{%
|
||||
\MakeUppercase\contentsname}{\MakeUppercase\contentsname}}%
|
||||
\phantomsection
|
||||
\addcontentsline{toc}{chapter}{Contents}
|
||||
\@starttoc{toc}%
|
||||
\if@restonecol\twocolumn\fi
|
||||
}
|
||||
\makeatother
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||
%%% lof trickery
|
||||
\makeatletter
|
||||
\renewcommand\listoffigures{%
|
||||
\if@twocolumn
|
||||
\@restonecoltrue\onecolumn
|
||||
\else
|
||||
\@restonecolfalse
|
||||
\fi
|
||||
\chapter*{\listfigurename
|
||||
\@mkboth{\MakeUppercase\listfigurename}%
|
||||
{\MakeUppercase\listfigurename}}%
|
||||
\phantomsection
|
||||
\addcontentsline{toc}{chapter}{List of Figures}
|
||||
\@starttoc{lof}%
|
||||
\if@restonecol\twocolumn\fi
|
||||
}
|
||||
\makeatother
|
||||
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
344
docs/Syntax.markdown
Normal file
344
docs/Syntax.markdown
Normal file
@ -0,0 +1,344 @@
|
||||
% Cryptol version 2 Syntax
|
||||
%
|
||||
%
|
||||
|
||||
Layout
|
||||
======
|
||||
|
||||
Groups of declarations are organized based on indentation.
|
||||
Declarations with the same indentation belong to the same group.
|
||||
Lines of text that are indented more than the beginning of a
|
||||
declaration belong to that declaration, while lines of text that are
|
||||
indented less terminate a group of declaration. Groups of
|
||||
declarations appear at the top level of a Cryptol file, and inside
|
||||
`where` blocks in expressions. For example, consider the following
|
||||
declaration group
|
||||
|
||||
f x = x + y + z
|
||||
where
|
||||
y = x * x
|
||||
z = x + y
|
||||
|
||||
g y = y
|
||||
|
||||
This group has two declaration, one for `f` and one for `g`. All the
|
||||
lines between `f` and `g` that are indented more then `f` belong to
|
||||
`f`.
|
||||
|
||||
This example also illustrates how groups of declarations may be nested
|
||||
within each other. For example, the `where` expression in the
|
||||
definition of `f` starts another group of declarations, containing `y`
|
||||
and `z`. This group ends just before `g`, because `g` is indented
|
||||
less than `y` and `z`.
|
||||
|
||||
Comments
|
||||
========
|
||||
|
||||
Cryptol supports block comments, which start with `/*` and end with
|
||||
`*/`, and line comments, which start with `//` and terminate at the
|
||||
end of the line. Block comments may be nested arbitrarily.
|
||||
|
||||
Examples:
|
||||
|
||||
/* This is a block comment */
|
||||
// This is a line comment
|
||||
/* This is a /* Nested */ block comment */
|
||||
|
||||
Identifiers
|
||||
===========
|
||||
|
||||
Cryptol identifiers consist of one or more characters. The first
|
||||
character must be either an English letter or underscore (`_`). The
|
||||
following characters may be an English letter, a decimal digit,
|
||||
underscore (`_`), or a prime (`'`). Some identifiers have special
|
||||
meaning in the language, so they may not be used in programmer-defined
|
||||
names (see [Keywords](#keywords-and-built-in-operators)).
|
||||
|
||||
Examples:
|
||||
|
||||
name name1 name' longer_name
|
||||
Name Name2 Name'' longerName
|
||||
|
||||
Keywords and Built-in Operators
|
||||
===============================
|
||||
|
||||
The following identifiers have special meanings in Cryptol, and may
|
||||
not be used for programmer defined names:
|
||||
|
||||
<!--- The table below can be generated by running `chop.hs` on this list:
|
||||
Arith
|
||||
Bit
|
||||
Cmp
|
||||
False
|
||||
Inf
|
||||
True
|
||||
else
|
||||
export
|
||||
extern
|
||||
fin
|
||||
if
|
||||
import
|
||||
inf
|
||||
lg2
|
||||
max
|
||||
min
|
||||
module
|
||||
newtype
|
||||
pragma
|
||||
property
|
||||
then
|
||||
type
|
||||
where
|
||||
width
|
||||
--->
|
||||
|
||||
Arith Inf extern inf module then
|
||||
Bit True fin lg2 newtype type
|
||||
Cmp else if max pragma where
|
||||
False export import min property width
|
||||
|
||||
The following table contains Cryptol's operators and their
|
||||
associativity with lowest precedence operators first, and highest
|
||||
precedence last.
|
||||
|
||||
Operator Associativity
|
||||
--------------- -------------
|
||||
`||` left
|
||||
`^` left
|
||||
`&&` left
|
||||
`->` (types) right
|
||||
`!=` `==` not associative
|
||||
`>` `<` `<=` `>=` not associative
|
||||
`#` right
|
||||
`>>` `<<` `>>>` `<<<` left
|
||||
`+` `-` left
|
||||
`*` `/` `%` left
|
||||
`^^` right
|
||||
`!` `!!` `@` `@@` left
|
||||
(unary) `-` `~` right
|
||||
|
||||
Table: Operator precedences.
|
||||
|
||||
Numeric Literals
|
||||
================
|
||||
|
||||
Numeric literals may be written in binary, octal, decimal, or
|
||||
hexadecimal notation. The base of a literal is determined by its
|
||||
prefix: `0b` for binary, `0o` for octal, no special prefix for
|
||||
decimal, and `0x` for hexadecimal.
|
||||
|
||||
Examples:
|
||||
|
||||
254 // Decimal literal
|
||||
0254 // Decimal literal
|
||||
0b11111110 // Binary literal
|
||||
0o376 // Octal literal
|
||||
0xFE // Hexadecimal literal
|
||||
0xfe // Hexadecimal literal
|
||||
|
||||
Numeric literals represent finite bit sequences (i.e., they have type
|
||||
`[n]`). Using binary, octal, and hexadecimal notation results in bit
|
||||
sequences of a fixed length, depending on the number of digits in the
|
||||
literal. Decimal literals are overloaded, and so the length of the
|
||||
sequence is inferred from context in which the literal is used.
|
||||
Examples:
|
||||
|
||||
0b1010 // : [4], 1 * number of digits
|
||||
0o1234 // : [12], 3 * number of digits
|
||||
0x1234 // : [16], 4 * number of digits
|
||||
|
||||
10 // : {n}. (fin n, n >= 4) => [n]
|
||||
// (need at least 4 bits)
|
||||
|
||||
0 // : {n}. (fin n) => [n]
|
||||
|
||||
Bits
|
||||
====
|
||||
|
||||
The type `Bit` has two inhabitants: `True` and `False`. These values
|
||||
may be combined using various logical operators, or constructed as
|
||||
results of comparisons.
|
||||
|
||||
Operator Associativity Description
|
||||
--------------------- ------------- -----------
|
||||
`||` left Logical or
|
||||
`^` left Exclusive-or
|
||||
`&&` left Logical and
|
||||
`!=` `==` none Not equals, equals
|
||||
`>` `<` `<=` `>=` none Comparisons
|
||||
`~` right Logical negation
|
||||
|
||||
Table: Bit operations.
|
||||
|
||||
If Then Else with Multiway
|
||||
==========================
|
||||
|
||||
`If then else` has been extended to support multi-way
|
||||
conditionals. Examples:
|
||||
|
||||
x = if y % 2 == 0 then 22 else 33
|
||||
|
||||
x = if y % 2 == 0 then 1
|
||||
| y % 3 == 0 then 2
|
||||
| y % 5 == 0 then 3
|
||||
else 7
|
||||
|
||||
Tuples and Records
|
||||
==================
|
||||
|
||||
Tuples and records are used for packaging multiples values together.
|
||||
Tuples are enclosed in parenthesis, while records are enclosed in
|
||||
braces. The components of both tuples and records are separated by
|
||||
commas. The components of tuples are expressions, while the
|
||||
components of records are a label and a value separated by an equal
|
||||
sign. Examples:
|
||||
|
||||
(1,2,3) // A tuple with 3 component
|
||||
() // A tuple with no components
|
||||
|
||||
{ x = 1, y = 2 } // A record with two fields, `x` and `y`
|
||||
{} // A record with no fileds
|
||||
|
||||
The components of tuples are identified by position, while the
|
||||
components of records are identified by their label, and so the
|
||||
ordering of record components is not important. Examples:
|
||||
|
||||
(1,2) == (1,2) // True
|
||||
(1,2) == (2,1) // False
|
||||
|
||||
{ x = 1, y = 2 } == { x = 1, y = 2 } // True
|
||||
{ x = 1, y = 2 } == { y = 2, x = 1 } // True
|
||||
|
||||
The components of a record or a tuple may be accessed in two ways: via
|
||||
pattern matching or by using explicit component selectors. Explicit
|
||||
component selectors are written as follows:
|
||||
|
||||
(15, 20).1 == 15
|
||||
(15, 20).2 == 20
|
||||
|
||||
{ x = 15, y = 20 }.x == 15
|
||||
|
||||
Explicit record selectors may be used only if the program contains
|
||||
sufficient type information to determine the shape of the tuple or
|
||||
record. For example:
|
||||
|
||||
type T = { sign :: Bit, number :: [15] }
|
||||
|
||||
// Valid defintion:
|
||||
// the type of the record is known.
|
||||
isPositive : T -> Bit
|
||||
isPositive x = x.sign
|
||||
|
||||
// Invalid defintion:
|
||||
// insufficient type information.
|
||||
badDef x = x.f
|
||||
|
||||
The components of a tuple or a record may also be access by using
|
||||
pattern matching. Patterns for tuples and records mirror the syntax
|
||||
for constructing values: tuple patterns use parenthesis, while record
|
||||
patterns use braces. Examples:
|
||||
|
||||
getFst (x,_) = x
|
||||
|
||||
distance2 { x = xPos, y = yPos } = xPos ^^ 2 + yPos ^^ 2
|
||||
|
||||
f x = fst + snd where
|
||||
|
||||
Sequences
|
||||
=========
|
||||
|
||||
A sequence is a fixed-length collection of element of the same type.
|
||||
The type of a finite sequence of length `n`, with elements of type `a`
|
||||
is `[n] a`. Often, a finite sequence of bits, `[n] Bit`, is called a
|
||||
_word_. We may abbreviate the type `[n] Bit` as `[n]`. An infinite
|
||||
sequence with elements of type `a` has type `[inf] a`, and `[inf]` is
|
||||
an infinite stream of bits.
|
||||
|
||||
[e1,e2,e3] // A sequence with three elements
|
||||
|
||||
[t .. ] // Sequence enumerations
|
||||
[t1, t2 .. ] // Step by t2 - t1
|
||||
[t1 .. t3 ]
|
||||
[t1, t2 .. t3 ]
|
||||
[e1 ... ] // Infinite sequence starting at e1
|
||||
[e1, e2 ... ] // Infinite sequence stepping by e2-e1
|
||||
|
||||
[ e | p11 <- e11, p12 <- e12 // Sequence comprehensions
|
||||
| p21 <- e21, p22 <- e22 ]
|
||||
|
||||
Note: the bounds in finite unbounded (those with ..) sequences are
|
||||
type expressions, while the bounds in bounded-finite and infinite
|
||||
sequences are value expressions.
|
||||
|
||||
Operator Description
|
||||
-------- -----------
|
||||
`#` Sequence concatenation
|
||||
`>>` `<<` Shift (right,left)
|
||||
`>>>` `<<<` Rotate (right,left)
|
||||
`@` `!` Access elements (front,back)
|
||||
`@@` `!!` Access sub-sequence (front,back)
|
||||
|
||||
Table: Sequence operations.
|
||||
|
||||
There are also lifted point-wise operations.
|
||||
|
||||
[p1, p2, p3, p4] // Sequence pattern
|
||||
p1 # p2 // Split sequence pattern
|
||||
|
||||
Functions
|
||||
=========
|
||||
|
||||
\p1 p2 -> e // Lambda expression
|
||||
f p1 p2 = e // Function definition
|
||||
|
||||
Local Declarations
|
||||
==================
|
||||
|
||||
e where ds
|
||||
|
||||
Explicit Type Instantiation
|
||||
===========================
|
||||
|
||||
If `f` is a polymorphic value with type:
|
||||
|
||||
f : { tyParam }
|
||||
|
||||
f `{ tyParam = t }
|
||||
|
||||
|
||||
Demoting Numeric Types to Values
|
||||
================================
|
||||
|
||||
The value corresponding to a numeric type may be accessed using the
|
||||
following notation:
|
||||
|
||||
`{t}
|
||||
|
||||
Here `t` should be a type expression with numeric kind. The resulting
|
||||
expression is a finite word, which is sufficiently large to accomodate
|
||||
the value of the type:
|
||||
|
||||
`{t} :: {w >= width t}. [w]
|
||||
|
||||
Explicit Type Annotations
|
||||
=========================
|
||||
|
||||
Explicit type annotations may be added on expressions, patterns, and
|
||||
in argument definitions.
|
||||
|
||||
e : t
|
||||
|
||||
p : t
|
||||
|
||||
f (x : t) = ...
|
||||
|
||||
Type Signatures
|
||||
===============
|
||||
|
||||
f,g : {a,b} (fin a) => [a] b
|
||||
|
||||
Type Synonym Declarations
|
||||
=========================
|
||||
|
||||
type T a b = [a] b
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user