%       Process with LaTeX  (Tested on LaTeX 2.09, PC-TeX 1.50f)
\documentstyle{article}
\topmargin -0.5in
\textheight 9in
\parskip 10pt
\parindent 0pt
\oddsidemargin -0.25in
\evensidemargin -0.25in
\textwidth 7in
\title{The Kelvinator\\
       {\large ``Go ahead, make my data.''}}
\author{by Kelvin R. Throop}
\date{Revision 3 ---  December 14, 1986}
\begin{document}
\maketitle

\subsection*{Background}

Following the release of AutoCAD version 2.1, independent developers
began to create complex applications employing the AutoCAD menu macro
language and the Variables and Expressions feature as an embedded
programming language.  With the release of version 2.18, which
introduced the AutoLisp programming language, AutoCAD became a fully
programmable system.

From inception, AutoCAD's open architecture has been intended to
encourage outside developers and individual users to customise AutoCAD
and implement applications for diverse markets.  Since menu macros
and AutoLisp are interpreted languages, applications must be shipped in
source code form, and Autodesk recognised the need to protect the
developers of these applications from theft of their proprietary
products.

Encryption of menu macros and AutoLisp programs was implemented and
made available to authorised developers.  This encryption never
purported to be particularly secure, but it does prevent casual
examination of distributed code.  Given that a standard AutoCAD must
be able to decode a file encrypted by any developer, there is no
cryptologic technique of which I am aware which would be significantly
more secure than the one used.  The fact that the encryption program
is made available to hundreds of developers who cannot always prevent
its further distribution makes penetration due to reverse engineering
of the program or a known-plaintext attack inevitable should somebody
be so callous as to undertake such an effort to steal the work of our
developers and undermine the viability of their businesses.

\subsection*{A Second Layer of Protection}

Since the encryption of files cannot provide total security, a
second level of defence may be called for.  The Kelvinator is a
program which translates an AutoLisp program into a form which is
essentially gibberish when examined by a human, but which should
execute identically to the original program.  Thus, if the distributed
program is decrypted, the resulting source code will be little use to
the looter.

Kelvination of a program consists of:

\begin{itemize}
        \item Deleting comments.
        \item Translating variable names into gibberish.
        \item Removing indentation and line breaks.
        \item Expressing numbers in canonical form.
\end{itemize}

As an example of the consequences of Kelvination, the following
AutoLisp program was processed.

\begin{verbatim}
;
;       Display spiral
;
;       Designed and implemented by Kelvin R. Throop on 1985 January 85
;
;       (cspiral <# rotations> <base point> <growth per rotation>
;                <points per circle>)
;
(defun cspiral (ntimes bpoint cfac lppass / ang dist tp ainc dinc circle bs cs)
        (setq cs (getvar "cmdecho"))
        (setq bs (getvar "blipmode"))
        (setvar "blipmode" 0)
        (setvar "cmdecho" 0)
        (setq circle (* 3.141596235 2))
        (setq ainc (/ circle lppass))
        (setq dinc (/ cfac lppass))
        (setq ang 0.0)
        (setq dist 0.0)
        (command "pline" bpoint)
        (repeat ntimes
           (repeat lppass
              (setq tp (polar bpoint (setq ang (+ ang ainc))
                          (setq dist (+ dist dinc))))
              (command tp)
           )
        )
        (command)
        (setvar "blipmode" bs)
        (setvar "cmdecho" cs)
        nil
)
;
;       Interactive spiral generation
;
(defun C:SPIRAL ( / nt bp cf lp)
        (prompt "\nCentre point: ")
        (setq bp (getpoint))
        (prompt "\nNumber of rotations: ")
        (setq nt (getint))
        (prompt "\nGrowth per rotation: ")
        (setq cf (getdist bp))
        (prompt "\nPoints per rotation: ")
        (setq lp (getint))
        (cond ((null lp) (setq lp 30)))
        (cspiral nt bp cf lp)
)
\end{verbatim}

The output of the Kelvinator is as follows (line breaks have been
manually inserted: there were none in the actual output file).

\begin{verbatim}
(DEFUN Qj (Q@ QQ Ql Q& / Q1 Q# Q0 Q$ QO Q| Q% Q?j) (SETQ Q?j (GETVAR
"cmdecho")) (SETQ Q% (GETVAR "blipmode")) (SETVAR "blipmode" 0)
(SETVAR "cmdecho" 0) (SETQ Q| (* 3.141596235 2)) (SETQ Q$ (/ Q| Q&))
(SETQ QO (/ Ql Q&)) (SETQ Q1 0.0) (SETQ Q# 0.0) (COMMAND "pline" QQ)
(REPEAT Q@ (REPEAT Q& (SETQ Q0 (POLAR QQ (SETQ Q1 (+ Q1 Q$)) (SETQ Q#
(+ Q# QO)))) (COMMAND Q0))) (COMMAND) (SETVAR "blipmode" Q%) (SETVAR
"cmdecho" Q?j) nil)(DEFUN C:SPIRAL (/ Qjj Q@j QQj Qlj) (PROMPT
"\nCentre point: ") (SETQ Q@j (GETPOINT)) (PROMPT "\nNumber of rotations: ")
(SETQ Qjj (GETINT)) (PROMPT "\nGrowth per rotation: ") (SETQ QQj
(GETDIST Q@j)) (PROMPT "\nPoints per rotation: ") (SETQ Qlj (GETINT))
(COND ((NULL Qlj) (SETQ Qlj 30))) (Qj Qjj Q@j QQj Qlj))
\end{verbatim}

If you imagine several thousand lines of this in a real application
instead of the few lines generated by this simple AutoLisp program
(which, by the way, was the first AutoLisp program ever written), it
should be clear that not much can be gleaned from decrypting such ``source
code''.

\subsection*{Kelvinating a File}

To Kelvinate a file, use the command:

{\tt \hspace{.5in} KELV }{\em ifile} {\tt [}{\em prefix}{\tt ]}

Input is read from the specified {\em ifile}.  If no file type is
specified, {\tt .LSP} is assumed.  Output is written to standard
output, and will usually be redirected to a file.  The {\em prefix}
argument is used only when Kelvinating programs with multiple source
modules and is described later in this document.  For example, to
Kelvinate the AutoLisp application {\tt BRAINSIM.LSP} and write the
output into {\tt UBRAINS.LSP}, use the command:

{\tt \hspace{.5in} KELV BRAINSIM >UBRAINS.LSP}

Hey, I know the input and output conventions in this programs are
somewhat odd, but it works, OK?  Given that this program is a brutally
hacked version of AutoLisp, the design makes implementation sense.

\subsubsection*{Untranslated Symbols}

Symbols defined by AutoLisp ({\tt CONS, SETQ, SSGET}) are not
translated.  User-defined symbols are always translated unless the
second character of the symbol is a colon (``:'').  This causes
command definition names (such as {\tt C:SPIRAL} in the example above)
not to be translated, and also allows an explicit escape if you wish
to preserve variable names.  This is usually done when
swapping programs using the {\tt LOAD} function and is used to pass
variables from the calling program to the one being loaded.  Variables
local to a given overlay should be translated, but those
shared by all overlays must be saved from translation by assigning
them names with a colon as the second character (such as {\tt G:INDEX},
{\tt U:23}, and {\tt P:USERNAME}).

\subsubsection*{Multiple Module Programs}

If an AutoLisp program is a single module which is loaded into AutoCAD
and run as a unit, the translation performed by the Kelvinator is
usually adequate.  If an application consists of more than one
original {\tt .LSP} file and the running program loads different
AutoLisp modules during execution, special care must be taken when
Kelvinating the application.  Simply running the Kelvinator on a
source file translates all the variable names in it into a standard
format.  If each module of a multiple module program were Kelvinated,
this would result in two distinct problems:

\begin{enumerate}
        \item Variables shared between modules would be given
              different names in different modules, so values
              passed would not be received correctly in the loaded
              module.
        \item Variables with distinct names in the original source
              might be translated into the same name in the Kelvinated
              output.  Thus duplication of variable names would almost
              certainly occur.
\end{enumerate}

The first problem may be solved by judicious application of the trick
of using a colon as the second character of the symbols shared between
modules described in the preceding section.  The second
requires use of an additional argument on the call to the Kelvinator
which permits generation of unique names for each module.  If the
Kelvinator is called with a {\em prefix} argument, the generated
variable names will begin with the specified prefix.  If no
prefix is specified, the default of ``Q'' is used.  The prefix may be
any string which is a valid AutoLisp symbol, but should not be a
symbol likely to duplicate an AutoLisp-defined symbol.  If you're
Kelvinating a four module electronic application, you might use:

\begin{verbatim}
        KELV ARISIA   ZA  >PARISIA.LSP
        KELV SCAPTURE ZB  >PSCAPT.LSP
        KELV PCBOARD  ZC  >PPCBD.LSP
        KELV SIMULATE ZD  >PSIM.LSP
\end{verbatim}

The respective modules will be given variable prefixes of {\tt ZA}
through {\tt ZD}, and are therefore guaranteed to be unique.  Remember
that AutoLisp is far more efficient when storing symbols of 6
characters or less, so don't go overboard in choosing a variable
prefix.  Two characters should be adequate.

\subsection*{Other Benefits of Kelvination}

Even if security is not a consideration, you might consider
Kelvinating your program.  By removing comments and white space, and
replacing long descriptive variable names with short cryptic ones,
Kelvination may radically reduce the size of an AutoLisp program.
For example, Kelvination of AutoShade reduced the {\tt ASHADE.LSP}
file from 55903 bytes to 17390 bytes, a reduction of more than three
to one (the code was heavily commented).  In addition, if you intend
to Kelvinate the file before shipment, you are free to use long
variable names for documentation purposes; Kelvination will reduce
them to short names that AutoLisp can store efficiently.

The only speed benefit of Kelvination is that gained while loading
because a Kelvinated file is usually smaller.  Once loaded, a
Kelvinated program will run in exactly the same time as a
non-Kelvinated one (unless shortening of variable names has increased
free memory and thus reduced garbage collections, which will yield a
small edge to the Kelvinated program).

\end{document}
