Initial import from internal repo

This commit is contained in:
Adam C. Foltzer 2014-04-17 15:34:25 -07:00
commit ba0a0e8576
425 changed files with 84737 additions and 0 deletions

17
.gitignore vendored Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View File

220
docs/CryptolPrims.markdown Normal file
View 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
View 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
View File

@ -0,0 +1,14 @@
*.SPELLNEW
*.SPELLOLD
*.aux
*.bbl
*.blg
*.brf
*.idx
*.ilg
*.ind
*.log
*.out
*.toc
.*.swp
/tmp

View 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

View File

@ -0,0 +1 @@
/auto

View 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

File diff suppressed because it is too large Load Diff

View 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:

View File

@ -0,0 +1,5 @@
Enigma.cry:
ln -s ../enigma/Enigma.cry .
test: Enigma.cry
cryptol-2 -b sanity.icry

View File

@ -0,0 +1,3 @@
:set warnDefaulting=off
:l AES.tex
sanityCheck

View 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:

View 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:

View 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},
}

View File

@ -0,0 +1 @@
/auto

View 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:

View File

@ -0,0 +1,9 @@
\chapter{Conclusion}
\label{cha:conclusion}
To be written.
%%% Local Variables:
%%% mode: latex
%%% TeX-master: "../main/Cryptol"
%%% End:

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Binary file not shown.

Binary file not shown.

View 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:

View File

@ -0,0 +1 @@
/auto

View 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)

View 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:

View 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:

View 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 ...] ]

View File

@ -0,0 +1,2 @@
test:
cryptol-2 -b sanity.icry

View 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 ]
*/

View File

@ -0,0 +1,3 @@
:set warnDefaulting=off
:l Enigma.tex
sanityCheck

View 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
]

View File

@ -0,0 +1 @@
/auto

File diff suppressed because it is too large Load Diff

View 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

View File

@ -0,0 +1,4 @@
:set warnDefaulting=off
:set prover=yices
:l HighAssurance.tex
:prove caesarCorrect : ([8], String(8)) -> Bit

View 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:

View File

@ -0,0 +1,5 @@
/Cryptol.glo
/Cryptol.ist
/Cryptol.pdf
/Cryptol.tdo
/auto

View 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}

View 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}

View 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:

View File

@ -0,0 +1 @@
/auto

View 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}

View 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 Javarelated 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:

View 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:

View 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:

View 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:

View 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

View File

@ -0,0 +1,3 @@
*.hi
*.o
compileProgrammingCryptol

View File

@ -0,0 +1,10 @@
.PHONY: all
all: compileProgrammingCryptol
@./compileProgrammingCryptol
compileProgrammingCryptol: compileProgrammingCryptol.hs
@ghc --make -o $@ $<
clean:
@rm -f *.hi *.o

View 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

View 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

View 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:

View 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:

View 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'.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

View 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'.

View 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

View 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/

File diff suppressed because it is too large Load Diff

View 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

Binary file not shown.

File diff suppressed because it is too large Load Diff

View 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'.

View File

@ -0,0 +1,3 @@
@rem = '-*- Perl -*-
@echo off
perl -S %~dp0makeglos.pl %*

View 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;

File diff suppressed because it is too large Load Diff

View 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'.

View 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'.

View 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'.

View 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'.

View 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'.

View 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'.

View 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'.

View 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'.

View 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
View 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