diff --git a/books/bookvol10.3.pamphlet b/books/bookvol10.3.pamphlet
index d80c974..d31717e 100644
--- a/books/bookvol10.3.pamphlet
+++ b/books/bookvol10.3.pamphlet
@@ -53695,6 +53695,1221 @@ HexadecimalExpansion(): Exports == Implementation where
 
 @
 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+\section{package HTMLFORM HTMLFormat}
+Here I have put some information about 'how to use' and 'the benefits of'
+this HTML formatter. Also some information for programmers if they want
+to extend this package.
+
+If you want information about creating output formatters in general then,
+rather than duplicating content here I refer you to mathml.spad.pamphlet
+containing the MathMLFormat domain by Arthur C. Ralfs. This contains useful
+information for writers of output formatters.
+
+\subsection{Overview}
+
+This package allows users to cut and paste output from the Axiom
+command line to a HTML page. This output is enabled by typing:
+
+\begin{verbatim}
+)set output html on
+\end{verbatim}
+
+After this the command line will output html (in addition to other formats
+that are enabled) and this html code can then be copied and pasted into a
+HTML document.
+
+The HTML produced is well formed XML, that is, all tags have equivalent
+closing tags.
+
+\subsection{Why output to HTML?}
+
+In some ways HTMLFormat is a compromise between the standard text output and
+specialised formats like MathMLFormat. The potential quality is never
+going to be as good as output to a specialised maths renderer but on
+the other hand it is a lot better than the clunky fixed width font
+text output. The quality is not the only issue though, the direct output
+in any format is unlikely to be exactly what the user wants, so possibly
+more important than quality is the ability to edit the output.
+
+HTMLFormat has advantages that the other output formats don't, for instance,
+\begin{itemize}
+\item It works with any browser without the need for plugins (as far as I know
+most computers should have the required fonts)
+\item Users can easily annotate and add comments using colour, bold, underline
+and so on.
+\item Annotations can easily be done with whatever html editor or text editor
+you are familiar with.
+\item Edits to the output will cause the width of columns and so on to be
+automatically adjusted, no need to try to insert spaces to get the
+superscripts to line up again!
+\item It is very easy to customise output so, for instance, we can fit a lot of
+information in a compact space on the page.
+\end{itemize}
+
+\section{Using the formatter}
+We can cause the command line interpreter to output in html by typing
+the following:
+
+\begin{verbatim}
+)set output html on
+\end{verbatim}
+
+After this the command line will output html (in addition to other formats
+that are enabled) and this html code can then be copied and pasted into an
+existing HTML document.
+
+If you do not already have an html page to copy the output to then you can
+create one with a text editor and entering the following:
+
+\begin{verbatim}
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" 
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" >
+ <head>
+  <title>Enter Your Title Here</title>
+ </head>
+ <body>
+  Copy and paste the output from command line here.
+ </body>
+</html>
+\end{verbatim}
+
+Or using any program that will export to html such as OpenOffice.org
+writer.
+
+\section{Form of the output}
+\begin{verbatim}
+HTMLFormat does not try to interpret syntax, for instance in an example like:
+(1) -> integral(x^x,x)
+it just takes what OutputForm provides and does not try to replace
+%A with the bound variable x.
+\end{verbatim}
+
+\section{Matrix Formatting}
+A big requirement for me is to fit big matrices on ordinary web pages.
+
+At the moment the default output for a matrix is a grid, however it easy to
+modify this for a single matrix, or a whole page or whole site by using css
+(cascading style sheets). For instance we can get a more conventional looking
+matrix by adding the following style to the top of the page after the <head>
+tag:
+
+\begin{verbatim}
+<style type="text/css">
+#matl {border-left-style:solid}
+#matr {border-right-style:solid}
+#matlt {border-left-style:solid;border-top-style:solid}
+#matrt {border-right-style:solid;border-top-style:solid}
+#matlb {border-left-style:solid;border-bottom-style:solid}
+#matrb {border-right-style:solid;border-bottom-style:solid}
+</style>
+\end{verbatim}
+
+There are many other possibilities, for instance we can generate a matrix
+with bars either side to indicate a determinant. All we have to do is
+change the css for the site, page or individual element.
+
+\section{Programmers Guide}
+This package converts from OutputForm, which is a hierarchical tree structure,
+to html which uses tags arranged in a hierarchical tree structure. So the
+package converts from one tree (graph) structure to another.
+
+This conversion is done in two stages using an intermediate Tree String
+structure. This Tree String structure represents HTML where:
+\begin{itemize}
+\item leafs represents unstructured text
+\item string in leafs contains the text
+\item non-leafs represents xml elements
+\item string in non-leafs represents xml attributes
+\end{itemize}
+
+This is created by traversing OutputForm while building up the Tree String
+structure.
+
+The second stage is to convert the Tree Structure to text. All text output
+is done using:
+\begin{verbatim}
+sayTeX$Lisp
+\end{verbatim}
+I have not produced and output to String as I don't know a way to append
+to a long string efficiently and I don't know how to insert carriage-
+returns into a String.
+
+\subsection{Future Developments}
+There would be some benefits in creating a XMLFormat category which would
+contain common elements for all xml formatted outputs such as HTMLFormat,
+MathMLFormat, SVGFormat and X3DFormat. However programming effort might
+be better spent creating a version of OutputForm which has better syntax
+information.
+
+<<HTMLFormat.input>>=
+)set break resume
+)sys rm -f HTMLFormat.output
+)spool HTMLFormat.output
+)set message test on
+)set message auto off
+)clear all
+
+--S 1 of 9
+)show HTMLFormat
+--R HTMLFormat  is a domain constructor
+--R Abbreviation for HTMLFormat is HTMLFORM 
+--R This constructor is exposed in this frame.
+--R Issue )edit bookvol10.3.pamphlet to see algebra source code for HTMLFORM 
+--R
+--R------------------------------- Operations --------------------------------
+--R ?=? : (%,%) -> Boolean                coerce : OutputForm -> String
+--R coerce : % -> OutputForm              coerceL : OutputForm -> String
+--R coerceS : OutputForm -> String        display : String -> Void
+--R exprex : OutputForm -> String         hash : % -> SingleInteger
+--R latex : % -> String                   ?~=? : (%,%) -> Boolean
+--R
+--E 1
+
+--S 2 of 9
+coerce("3+4"::OutputForm)$HTMLFORM
+--R 
+--R"3+4"
+--R
+--R   (1)  " "
+--R                                                                 Type: String
+--E 2
+
+--S 3 of 9
+coerce("sqrt(3+4)"::OutputForm)$HTMLFORM
+--R 
+--R"sqrt(3+4)"
+--R
+--R   (2)  " "
+--R                                                                 Type: String
+--E 3
+
+--S 4 of 9
+coerce(sqrt(3+4)::OutputForm)$HTMLFORM
+--R 
+--R&radic;7
+--R
+--R   (3)  " "
+--R                                                                 Type: String
+--E 4
+
+--S 5 of 9
+coerce(sqrt(3+x)::OutputForm)$HTMLFORM
+--R 
+--R<table border='0' id='root'>
+--R<tr id='root'>
+--R<td id='root'>
+--R&radic;
+--R</td>
+--R<td id='root' style='border-top-style:solid'>
+--Rx+3
+--R</td>
+--R</tr>
+--R</table>
+--R
+--R   (4)  " "
+--R                                                                 Type: String
+--E 5
+
+--S 6 of 9
+coerceS(sqrt(3+x)::OutputForm)$HTMLFORM
+--R 
+--R<table border='0' id='root'>
+--R<tr id='root'>
+--R<td id='root'>
+--R&radic;
+--R</td>
+--R<td id='root' style='border-top-style:solid'>
+--Rx+3
+--R</td>
+--R</tr>
+--R</table>
+--R
+--R   (5)  " "
+--R                                                                 Type: String
+--E 6
+
+--S 7 of 9
+coerceL(sqrt(3+x)::OutputForm)$HTMLFORM
+--R 
+--R<table border='0' id='root'>
+--R<tr id='root'>
+--R<td id='root'>
+--R&radic;
+--R</td>
+--R<td id='root' style='border-top-style:solid'>
+--Rx+3
+--R</td>
+--R</tr>
+--R</table>
+--R
+--R   (6)  " "
+--R                                                                 Type: String
+--E 7
+
+--S 8 of 9
+exprex(sqrt(3+x)::OutputForm)$HTMLFORM
+--R 
+--R
+--R   (7)  "{{ROOT}{{+}{x}{3}}}"
+--R                                                                 Type: String
+--E 8
+
+--S 9 of 9
+display(coerce(sqrt(3+x)::OutputForm)$HTMLFORM)$HTMLFORM
+--R 
+--R<table border='0' id='root'>
+--R<tr id='root'>
+--R<td id='root'>
+--R&radic;
+--R</td>
+--R<td id='root' style='border-top-style:solid'>
+--Rx+3
+--R</td>
+--R</tr>
+--R</table>
+--R 
+--R                                                                   Type: Void
+--E 9
+)spool
+)lisp (bye)
+@
+<<HTMLFormat.help>>=
+====================================================================
+HTMLFormat examples
+====================================================================
+
+coerce("3+4"::OutputForm)$HTMLFORM
+  "3+4"
+
+coerce("sqrt(3+4)"::OutputForm)$HTMLFORM
+  "sqrt(3+4)"
+
+coerce(sqrt(3+4)::OutputForm)$HTMLFORM
+  &radic;7
+
+coerce(sqrt(3+x)::OutputForm)$HTMLFORM
+  <table border='0' id='root'>
+  <tr id='root'>
+  <td id='root'>
+  &radic;
+  </td>
+  <td id='root' style='border-top-style:solid'>
+  x+3
+  </td>
+  </tr>
+  </table>
+
+coerceS(sqrt(3+x)::OutputForm)$HTMLFORM
+  <table border='0' id='root'>
+  <tr id='root'>
+  <td id='root'>
+  &radic;
+  </td>
+  <td id='root' style='border-top-style:solid'>
+  x+3
+  </td>
+  </tr>
+  </table>
+
+coerceL(sqrt(3+x)::OutputForm)$HTMLFORM
+  <table border='0' id='root'>
+  <tr id='root'>
+  <td id='root'>
+  &radic;
+  </td>
+  <td id='root' style='border-top-style:solid'>
+  x+3
+  </td>
+  </tr>
+  </table>
+
+exprex(sqrt(3+x)::OutputForm)$HTMLFORM
+  "{{ROOT}{{+}{x}{3}}}"
+
+display(coerce(sqrt(3+x)::OutputForm)$HTMLFORM)$HTMLFORM
+  <table border='0' id='root'>
+  <tr id='root'>
+  <td id='root'>
+  &radic;
+  </td>
+  <td id='root' style='border-top-style:solid'>
+  x+3
+  </td>
+  </tr>
+  </table>
+
+See Also:
+o )show HTMLFormat
+
+@
+
+\pagehead{HTMLFormat}{HTMLFORM}
+\pagepic{ps/v103htmlformat.eps}{HTMLFORM}{1.00}
+{\bf See}\\
+\pagefrom{SetCategory}{SETCAT}
+
+{\bf Exports:}\\
+\begin{tabular}{lllll}
+\cross{HTMLFORM}{?=?} &
+\cross{HTMLFORM}{?~=?} &
+\cross{HTMLFORM}{coerce} &
+\cross{HTMLFORM}{coerceL} &
+\cross{HTMLFORM}{coerceS} \\
+\cross{HTMLFORM}{display} &
+\cross{HTMLFORM}{exprex} &
+\cross{HTMLFORM}{hash} &
+\cross{HTMLFORM}{latex} &
+\end{tabular}
+
+<<domain HTMLFORM HTMLFormat>>=
+)abbrev domain HTMLFORM HTMLFormat
+++ Author: Martin J Baker, Arthur C. Ralfs, Robert S. Sutor
+++ Date: January 2010
+++ Description:
+++ HtmlFormat provides a coercion from OutputForm to html.
+HTMLFormat(): public == private where
+  E      ==> OutputForm
+  I      ==> Integer
+  L      ==> List
+  S      ==> String
+
+  public == SetCategory with
+    coerce:    E -> S
+      ++ coerce(o) changes o in the standard output format to html format.
+      ++
+      ++X coerce(sqrt(3+x)::OutputForm)$HTMLFORM
+    coerceS:   E -> S
+      ++ coerceS(o) changes o in the standard output format to html
+      ++ format and displays formatted result.
+      ++
+      ++X coerceS(sqrt(3+x)::OutputForm)$HTMLFORM
+    coerceL:   E -> S
+      ++ coerceL(o) changes o in the standard output format to html
+      ++ format and displays result as one long string.
+      ++
+      ++X coerceL(sqrt(3+x)::OutputForm)$HTMLFORM
+    exprex:    E -> S
+      ++ exprex(o) coverts \spadtype{OutputForm} to \spadtype{String}
+      ++
+      ++X exprex(sqrt(3+x)::OutputForm)$HTMLFORM
+    display:   S -> Void
+      ++ display(o) prints the string returned by coerce.
+      ++
+      ++X display(coerce(sqrt(3+x)::OutputForm)$HTMLFORM)$HTMLFORM
+
+  private == add
+    import OutputForm
+    import Character
+    import Integer
+    import List OutputForm
+    import List String
+
+    expr: E
+    prec,opPrec: I
+    str:  S
+    blank         : S := " \  "
+
+    maxPrec       : I   := 1000000
+    minPrec       : I   := 0
+
+    unaryOps      : L S := ["-"]$(L S)
+    unaryPrecs    : L I := [700]$(L I)
+
+    -- the precedence of / in the following is relatively low because
+    -- the bar obviates the need for parentheses.
+    binaryOps     : L S := ["+->","|","^","/","<",">","=","OVER"]$(L S)
+    binaryPrecs   : L I := [0,0,900,700,400,400,400,700]$(L I)
+    naryOps       : L S := ["-","+","*",blank,",",";"," ","ROW","",
+       " \cr ","&","/\","\/"]$(L S)
+    naryPrecs     : L I := [700,700,800,800,110,110,0,0,0,0,0,600,600]$(L I)
+    naryNGOps     : L S := ["ROW","&"]$(L S)
+    plexOps       : L S := ["SIGMA","SIGMA2","PI","PI2","INTSIGN",_
+                            "INDEFINTEGRAL"]$(L S)
+    plexPrecs     : L I := [700,800,700,800,700,700]$(L I)
+    specialOps    : L S := ["MATRIX","BRACKET","BRACE","CONCATB","VCONCAT",_
+                            "AGGLST","CONCAT","OVERBAR","ROOT","SUB","TAG",_
+                            "SUPERSUB","ZAG","AGGSET","SC","PAREN",_
+                            "SEGMENT","QUOTE","theMap", "SLASH"]
+
+    -- the next two lists provide translations for some strings for
+    -- which HTML has some special character codes.
+    specialStrings : L S :=
+      ["cos", "cot", "csc", "log", "sec", "sin", "tan", _
+       "cosh", "coth", "csch", "sech", "sinh", "tanh", _
+       "acos","asin","atan","erf","...","$","infinity","Gamma", _
+       "%pi","%e","%i"]
+    specialStringsInHTML : L S :=
+      ["cos","cot","csc","log","sec","sin","tan", _
+       "cosh","coth","csch","sech","sinh","tanh", _
+       "arccos","arcsin","arctan","erf","&#x2026;","$","&#x221E;",_
+       "&#x0413;","&#x003C0;","&#x02147;","&#x02148;"]
+
+    debug := false
+
+    atomize:E -> L E
+
+    formatBinary:(S,L E, I) -> Tree S
+
+    formatFunction:(Tree S,L E, I) -> Tree S
+
+    formatMatrix:L E -> Tree S
+
+    formatNary:(S,L E, I) -> Tree S
+
+    formatNaryNoGroup:(S,L E, I) -> Tree S
+
+    formatNullary:S -> Tree S
+
+    formatPlex:(S,L E, I) -> Tree S
+
+    formatSpecial:(S,L E, I) -> Tree S
+
+    formatUnary:(S,  E, I) -> Tree S
+
+    formatHtml:(E,I) -> Tree S
+
+    precondition:E -> E
+      -- this function is applied to the OutputForm expression before
+      -- doing anything else.
+
+    outputTree:Tree S -> Void
+      -- This function traverses the tree and linierises it into a string.
+      -- To get the formatting we use a nested set of tables. It also checks
+      -- for +- and removes the +. it may also need to remove the outer
+      -- set of brackets.
+
+    stringify:E -> S
+
+    coerce(expr : E): S ==
+      outputTree formatHtml(precondition expr, minPrec)
+      " "
+
+    coerceS(expr : E): S ==
+      outputTree formatHtml(precondition expr, minPrec)
+      " "
+
+    coerceL(expr : E): S ==
+      outputTree formatHtml(precondition expr, minPrec)
+      " "
+
+    display(html : S): Void ==
+      sayTeX$Lisp html
+      void()$Void
+
+    newNode(tag:S,node: Tree S): (Tree S) ==
+      t := tree(S,[node])
+      setvalue!(t,tag)
+      t
+
+    newNodes(tag:S,nodes: L Tree S): (Tree S) ==
+      t := tree(S,nodes)
+      setvalue!(t,tag)
+      t
+
+    -- returns true if this can be represented without a table
+    notTable?(node: Tree S): Boolean ==
+      empty?(node) => true
+      leaf?(node) => true
+      prefix?("table",value(node))$String => false
+      c := children(node)
+      for a in c repeat
+        if not notTable?(a) then return false
+      true
+
+    -- this retuns a string representation of OutputForm arguments
+    -- it is used when debug is true to trace the calling of functions
+    -- in this package
+    argsToString(args : L E): S ==
+      sop : S := exprex first args
+      args := rest args
+      s : S := concat ["{",sop]
+      for a in args repeat
+          s1 : S := exprex a
+          s := concat [s,s1]
+      s := concat [s,"}"]
+
+    exprex(expr : E): S ==
+      -- This breaks down an expression into atoms and returns it as
+      -- a string.  It's for developmental purposes to help understand
+      -- the expressions.
+      a : E
+      expr := precondition expr
+      (ATOM(expr)$Lisp@Boolean) or (stringify expr = "NOTHING") =>
+        concat ["{",stringify expr,"}"]
+      le : L E := (expr pretend L E)
+      op := first le
+      sop : S := exprex op
+      args : L E := rest le
+      nargs : I := #args
+      s : S := concat ["{",sop]
+      if nargs > 0  then
+        for a in args repeat
+          s1 : S := exprex a
+          s := concat [s,s1]
+      s := concat [s,"}"]
+
+    atomize(expr : E): L E ==
+      -- This breaks down an expression into a flat list of atomic
+      -- expressions.
+      -- expr should be preconditioned.
+      le : L E := nil()
+      a : E
+      letmp : L E
+      (ATOM(expr)$Lisp@Boolean) or (stringify expr = "NOTHING") =>
+        le := append(le,list(expr))
+      letmp := expr pretend L E
+      for a in letmp repeat
+        le := append(le,atomize a)
+      le
+
+    -- output html test using tables and
+    -- remove unnecessary '+' at end of first string
+    -- when second string starts with '-'
+    outputTree(t: Tree S): Void ==
+      endWithPlus:Boolean := false -- if the last string ends with '+'
+      -- and the next string starts with '-' then the '+' needs to be
+      -- removed
+      if empty?(t) then
+        --if debug then sayTeX$Lisp "outputTree empty"
+        return void()$Void
+      if leaf?(t) then
+        --if debug then sayTeX$Lisp concat("outputTree leaf:",value(t))
+        sayTeX$Lisp value(t)
+        return void()$Void
+      tagName := copy value(t)
+      tagPos := position(char(" "),tagName,1)$String
+      if tagPos > 1 then
+        tagName := split(tagName,char(" ")).1
+        --sayTeX$Lisp "outputTree: tagPos="string(tagPos)" "tagName
+      if value(t) ~= "" then sayTeX$Lisp concat ["<",value(t),">"]
+      c := children(t)
+      enableGrid:Boolean := (#c > 1) and not notTable?(t)
+      if enableGrid then
+        if tagName = "table" then enableGrid := false
+        if tagName = "tr" then enableGrid := false
+      b:List Boolean := [leaf?(c1) for c1 in c]
+      -- if all children are strings then no need to wrap in table
+      allString: Boolean := true
+      for c1 in c repeat if not leaf?(c1) then allString := false
+      if allString then
+        s:String := ""
+        for c1 in c repeat s := concat(s,value(c1))
+        sayTeX$Lisp s
+        if value(t) ~= "" then sayTeX$Lisp concat ["</",tagName,">"]
+        return void()$Void
+      if enableGrid then
+        sayTeX$Lisp "<table border='0'>"
+        sayTeX$Lisp "<tr>"
+      for c1 in c repeat
+        if enableGrid then sayTeX$Lisp "<td>"
+        outputTree(c1)
+        if enableGrid then sayTeX$Lisp "</td>"
+      if enableGrid then
+        sayTeX$Lisp "</tr>"
+        sayTeX$Lisp "</table>"
+      if value(t) ~= "" then sayTeX$Lisp concat ["</",tagName,">"]
+      void()$Void
+
+    stringify expr == (mathObject2String$Lisp expr)@S
+
+    precondition expr ==
+      outputTran$Lisp expr
+
+    -- I dont know what SC is so put it in a table for now
+    formatSC(args : L E, prec : I)  : Tree S ==
+      if debug then sayTeX$Lisp "formatSC: "concat [" args=",_
+        argsToString(args)," prec=",string(prec)$S]
+      null args => tree("")
+      cells:L Tree S := [_
+        newNode("td id='sc' style='border-bottom-style:solid'",_
+        formatHtml(a,prec)) for a in args]
+      row:Tree S := newNodes("tr id='sc'",cells)
+      newNode("table border='0' id='sc'",row)
+
+    -- to build an overbar we put it in a single column,
+    -- single row table and set the top border to solid
+    buildOverbar(content : Tree S) : Tree S ==
+      if debug then sayTeX$Lisp "buildOverbar"
+      cell:Tree S := _
+        newNode("td id='overbar' style='border-top-style:solid'",content)
+      row:Tree S := newNode("tr id='overbar'",cell)
+      newNode("table border='0' id='overbar'",row)
+
+    -- to build an square root we put it in a double column,
+    -- single row table and set the top border of the second column to
+    -- solid
+    buildRoot(content : Tree S) : Tree S ==
+      if debug then sayTeX$Lisp "buildRoot"
+      if leaf?(content) then
+        -- root of a single term so no need for overbar
+        return newNodes("",[tree("&radic;"),content])
+      cell1:Tree S := newNode("td id='root'",tree("&radic;"))
+      cell2:Tree S := _
+        newNode("td id='root' style='border-top-style:solid'",content)
+      row:Tree S := newNodes("tr id='root'",[cell1,cell2])
+      newNode("table border='0' id='root'",row)
+
+    -- to build an 'n'th root we put it in a double column,
+    -- single row table and set the top border of the second column to
+    -- solid
+    buildNRoot(content : Tree S,nth: Tree S) : Tree S ==
+      if debug then sayTeX$Lisp "buildNRoot"
+      power:Tree S := newNode("sup",nth)
+      if leaf?(content) then
+        -- root of a single term so no need for overbar
+        return newNodes("",[power,tree("&radic;"),content])
+      cell1:Tree S := newNodes("td id='nroot'",[power,tree("&radic;")])
+      cell2:Tree S := _
+        newNode("td id='nroot' style='border-top-style:solid'",content)
+      row:Tree S := newNodes("tr id='nroot'",[cell1,cell2])
+      newNode("table border='0' id='nroot'",row)
+
+    -- formatSpecial handles "theMap","AGGLST","AGGSET","TAG","SLASH",
+    -- "VCONCAT", "CONCATB","CONCAT","QUOTE","BRACKET","BRACE","PAREN",
+    -- "OVERBAR","ROOT", "SEGMENT","SC","MATRIX","ZAG"
+    -- note "SUB" and "SUPERSUB" are handled directly by formatHtml
+    formatSpecial(op : S, args : L E, prec : I) : Tree S ==
+      if debug then sayTeX$Lisp _
+        "formatSpecial: " concat ["op=",op," args=",argsToString(args),_
+          " prec=",string(prec)$S]
+      arg : E
+      prescript : Boolean := false
+      op = "theMap" => tree("theMap(...)")
+      op = "AGGLST" =>
+        formatNary(",",args,prec)
+      op = "AGGSET" =>
+        formatNary(";",args,prec)
+      op = "TAG" =>
+        newNodes("",[formatHtml(first args,prec),tree("&#x02192;"),_
+          formatHtml(second args,prec)])
+        --RightArrow
+      op = "SLASH" =>
+        newNodes("",[formatHtml(first args, prec),tree("/"),_
+          formatHtml(second args,prec)])
+      op = "VCONCAT" =>
+        newNodes("table",[newNode("td",formatHtml(u, minPrec))_
+           for u in args]::L Tree S)
+      op = "CONCATB" =>
+        formatNary(" ",args,prec)
+      op = "CONCAT" =>
+        formatNary("",args,minPrec)
+      op = "QUOTE" =>
+        newNodes("",[tree("'"),formatHtml(first args, minPrec)])
+      op = "BRACKET" =>
+        newNodes("",[tree("["),formatHtml(first args, minPrec),tree("]")])
+      op = "BRACE" =>
+        newNodes("",[tree("{"),formatHtml(first args, minPrec),tree("}")])
+      op = "PAREN" =>
+        newNodes("",[tree("("),formatHtml(first args, minPrec),tree(")")])
+      op = "OVERBAR" =>
+        null args => tree("")
+        buildOverbar(formatHtml(first args,minPrec))
+      op = "ROOT" and #args < 1 => tree("")
+      op = "ROOT" and #args = 1 => _
+        buildRoot(formatHtml(first args, minPrec))
+      op = "ROOT" and #args > 1 => _
+        buildNRoot(formatHtml(first args, minPrec),_
+          formatHtml(second args, minPrec))
+      op = "SEGMENT" =>
+        -- '..' indicates a range in a list for example
+        tmp : Tree S := newNodes("",[formatHtml(first args, minPrec),_
+          tree("..")])
+        null rest args =>  tmp
+        newNodes("",[tmp,formatHtml(first rest args, minPrec)])
+      op = "SC" => formatSC(args,minPrec)
+      op = "MATRIX" => formatMatrix rest args
+      op = "ZAG" =>
+        -- {{+}{3}{{ZAG}{1}{7}}{{ZAG}{1}{15}}{{ZAG}{1}{1}}{{ZAG}{1}{25}}_
+        --      {{ZAG}{1}{1}}{{ZAG}{1}{7}}{{ZAG}{1}{4}}}
+        -- to format continued fraction traditionally need to intercept
+        -- it at the formatNary of the "+"
+        newNodes("",[tree(" \zag{"),formatHtml(first args, minPrec),
+          tree("}{"),
+          formatHtml(first rest args,minPrec),tree("}")])
+      tree("formatSpecial not implemented:"op)
+
+    formatSuperSub(expr : E, args : L E, opPrec : I) : Tree S ==
+      -- This one produces ordinary derivatives with differential notation,
+      -- it needs a little more work yet.
+      -- first have to divine the semantics, add cases as needed
+      if debug then sayTeX$Lisp _
+        "formatSuperSub: " concat ["expr=",stringify expr," args=",_
+          argsToString(args)," prec=",string(opPrec)$S]
+      atomE : L E := atomize(expr)
+      op : S := stringify first atomE
+      op ~= "SUPERSUB" => tree("Mistake in formatSuperSub: no SUPERSUB")
+      #args ~= 1 => tree("Mistake in SuperSub: #args <> 1")
+      var : E := first args
+      -- should be looking at something like {{SUPERSUB}{var}{ }{,,...,}}
+      -- for example here's the second derivative of y w.r.t. x
+      -- {{{SUPERSUB}{y}{ }{,,}}{x}}, expr is the first {} and args is the
+      -- {x}
+      funcS : S := stringify first rest atomE
+      bvarS : S := stringify first args
+      -- count the number of commas
+      commaS : S := stringify first rest rest rest atomE
+      commaTest : S := ","
+      ndiffs : I := 0
+      while position(commaTest,commaS,1) > 0 repeat
+        ndiffs := ndiffs+1
+        commaTest := commaTest","
+      res:Tree S := newNodes("",_
+        [tree("&#x02146;"string(ndiffs)""funcS"&#x02146;"),_
+          formatHtml(first args,minPrec),tree(""string(ndiffs)"&#x02061;"),_
+            formatHtml(first args,minPrec),tree(")")])
+      res
+
+    -- build structure such as integral as a table
+    buildPlex3(main:Tree S,supsc:Tree S,op:Tree S,subsc:Tree S) : Tree S ==
+      if debug then sayTeX$Lisp "buildPlex"
+      ssup:Tree S := newNode("td id='plex'",supsc)
+      sop:Tree S := newNode("td id='plex'",op)
+      ssub:Tree S := newNode("td id='plex'",subsc)
+      m:Tree S := newNode("td rowspan='3' id='plex'",main)
+      rows:(List Tree S) := [newNodes("tr id='plex'",[ssup,m]),_
+        newNode("tr id='plex'",sop),newNode("tr id='plex'",ssub)]
+      newNodes("table border='0' id='plex'",rows)
+
+    -- build structure such as integral as a table
+    buildPlex2(main : Tree S,supsc : Tree S,op : Tree S) : Tree S ==
+      if debug then sayTeX$Lisp "buildPlex"
+      ssup:Tree S := newNode("td id='plex'",supsc)
+      sop:Tree S := newNode("td id='plex'",op)
+      m:Tree S := newNode("td rowspan='2' id='plex'",main)
+      rows:(List Tree S) := [newNodes("tr id='plex'",[sop,m]),_
+        newNode("tr id='plex'",ssup)]
+      newNodes("table border='0' id='plex'",rows)
+
+    -- format an integral
+    -- args.1 = "NOTHING"
+    -- args.2 = bound variable
+    -- args.3 = body, thing being integrated
+    --
+    -- axiom replaces the bound variable with somthing like
+    -- %A and puts the original variable used
+    -- in the input command as a superscript on the integral sign.
+    formatIntSign(args : L E, opPrec : I) : Tree S ==
+      -- the original OutputForm expression looks something like this:
+      -- {{INTSIGN}{NOTHING or lower limit?}
+      -- {bvar or upper limit?}{{*}{integrand}{{CONCAT}{d}{axiom var}}}}
+      -- the args list passed here consists of the rest of this list, i.e.
+      -- starting at the NOTHING or ...
+      if debug then sayTeX$Lisp "formatIntSign: " concat [" args=",_
+        argsToString(args)," prec=",string(opPrec)$S]
+      (stringify first args) = "NOTHING" =>
+        buildPlex2(formatHtml(args.3,opPrec),tree("&int;"),_
+          formatHtml(args.2,opPrec)) -- could use &#x0222B; or &int;
+      buildPlex3(formatHtml(first args,opPrec),formatHtml(args.3,opPrec),_
+        tree("&int;"),formatHtml(args.2,opPrec))
+
+    -- plex ops are "SIGMA","SIGMA2","PI","PI2","INTSIGN","INDEFINTEGRAL"
+    -- expects 2 or 3 args
+    formatPlex(op : S, args : L E, prec : I) : Tree S ==
+      if debug then sayTeX$Lisp "formatPlex: " concat ["op=",op," args=",_
+        argsToString(args)," prec=",string(prec)$S]
+      checkarg:Boolean := false
+      hold : S
+      p : I := position(op,plexOps)
+      p < 1 => error "unknown plex op"
+      op = "INTSIGN" => formatIntSign(args,minPrec)
+      opPrec := plexPrecs.p
+      n : I := #args
+      (n ~= 2) and (n ~= 3) => error "wrong number of arguments for plex"
+      s : Tree S :=
+        op = "SIGMA"   =>
+          checkarg := true
+          tree("&#x02211;")
+        -- Sum
+        op = "SIGMA2"   =>
+          checkarg := true
+          tree("&#x02211;")
+        -- Sum
+        op = "PI"      =>
+          checkarg := true
+          tree("&#x0220F;")
+        -- Product
+        op = "PI2"     =>
+          checkarg := true
+          tree("&#x0220F;")
+        -- Product
+        op = "INTSIGN" => tree("&#x0222B;")
+        -- Integral, int
+        op = "INDEFINTEGRAL" => tree("&#x0222B;")
+        -- Integral, int
+        tree("formatPlex: unexpected op:"op)
+      -- if opPrec < prec then perhaps we should parenthesize?
+      -- but we need to be careful we don't get loads of unnecessary
+      -- brackets
+      if n=2 then return buildPlex2(formatHtml(first args,minPrec),_
+        formatHtml(args.2,minPrec),s)
+      buildPlex3(formatHtml(first args,minPrec),formatHtml(args.2,minPrec),_
+        s,formatHtml(args.3,minPrec))
+
+    -- an example is: op=ROW arg={{ROW}{1}{2}}
+    formatMatrixRow(op : S, arg : E, prec : I,y:I,h:I)  : L Tree S ==
+      if debug then sayTeX$Lisp "formatMatrixRow: " concat ["op=",op,_
+        " args=",stringify arg," prec=",string(prec)$S]
+      ATOM(arg)$Lisp@Boolean => [_
+        tree("formatMatrixRow does not contain row")]
+      l : L E := (arg pretend L E)
+      op : S := stringify first l
+      args : L E := rest l
+      --sayTeX$Lisp "formatMatrixRow op="op" args="argsToString(args)
+      w:I := #args
+      cells:(List Tree S) := empty()
+      for x in 1..w repeat
+        --sayTeX$Lisp "formatMatrixRow: x="string(x)$S" width="string(w)$S
+        attrib:S := "td id='mat'"
+        if x=1 then attrib := "td id='matl'"
+        if x=w then attrib := "td id='matr'"
+        if y=1 then attrib := "td id='matt'"
+        if y=h then attrib := "td id='matb'"
+        if x=1 and y=1 then attrib := "td id='matlt'"
+        if x=1 and y=h then attrib := "td id='matlb'"
+        if x=w and y=1  then attrib := "td id='matrt'"
+        if x=w and y=h  then attrib := "td id='matrb'"
+        cells := append(cells,[newNode(attrib,formatHtml(args.(x),prec))])
+      cells
+
+    -- an example is: op=MATRIX args={{ROW}{1}{2}}{{ROW}{3}{4}}
+    formatMatrixContent(op : S, args : L E, prec : I)  : L Tree S ==
+      if debug then sayTeX$Lisp "formatMatrixContent: " concat ["op=",op,_
+        " args=",argsToString(args)," prec=",string(prec)$S]
+      y:I := 0
+      rows:(List Tree S) := [newNodes("tr id='mat'",_
+        formatMatrixRow("ROW",e,prec,y:=y+1,#args)) for e in args]
+      rows
+
+    formatMatrix(args : L E) : Tree S ==
+      -- format for args is [[ROW ...],[ROW ...],[ROW ...]]
+      -- generate string for formatting columns (centered)
+      if debug then sayTeX$Lisp "formatMatrix: " concat ["args=",_
+        argsToString(args)]
+      newNodes("table border='1' id='mat'",_
+        formatMatrixContent("MATRIX",args,minPrec))
+
+    -- output arguments in column table
+    buildColumnTable(elements : List Tree S) : Tree S ==
+      if debug then sayTeX$Lisp "buildColumnTable"
+      cells:(List Tree S) := [newNode("td id='col'",j) for j in elements]
+      rows:(List Tree S) := [newNode("tr id='col'",i) for i in cells]
+      newNodes("table border='0' id='col'",rows)
+
+    -- build superscript structure as either sup tag or
+    -- if it contains anything that won't go into a
+    -- sup tag then build it as a table
+    buildSuperscript(main : Tree S,super : Tree S) : Tree S ==
+      if debug then sayTeX$Lisp "buildSuperscript"
+      notTable?(super) => newNodes("",[main,newNode("sup",super)])
+      m:Tree S := newNode("td rowspan='2' id='sup'",main)
+      su:Tree S := newNode("td id='sup'",super)
+      e:Tree S := newNode("td id='sup'",tree("&nbsp;"))
+      rows:(List Tree S) := [newNodes("tr id='sup'",[m,su]),_
+        newNode("tr id='sup'",e)]
+      newNodes("table border='0' id='sup'",rows)
+
+    -- build subscript structure as either sub tag or
+    -- if it contains anything that won't go into a
+    -- sub tag then build it as a table
+    buildSubscript(main : Tree S,subsc : Tree S) : Tree S ==
+      if debug then sayTeX$Lisp "buildSubscript"
+      notTable?(subsc) => newNodes("",[main,newNode("sub",subsc)])
+      m:Tree S := newNode("td rowspan='2' id='sub'",main)
+      su:Tree S := newNode("td id='sub'",subsc)
+      e:Tree S := newNode("td id='sub'",tree("&nbsp;"))
+      rows:(List Tree S) := [newNodes("tr id='sub'",[m,e]),_
+        newNode("tr id='sub'",su)]
+      newNodes("table border='0' id='sub'",rows)
+
+    formatSub(expr : E, args : L E, opPrec : I) : Tree S ==
+      -- format subscript
+      -- this function expects expr to start with SUB
+      -- it expects first args to be the operator or value that
+      -- the subscript is applied to
+      -- and the rest args to be the subscript
+      if debug then sayTeX$Lisp "formatSub: " concat ["expr=",_
+        stringify expr," args=",argsToString(args)," prec=",_
+          string(opPrec)$S]
+      atomE : L E := atomize(expr)
+      if empty?(atomE) then
+        if debug then sayTeX$Lisp "formatSub: expr=empty"
+        return tree("formatSub: expr=empty")
+      op : S := stringify first atomE
+      op ~= "SUB" =>
+        if debug then sayTeX$Lisp "formatSub: expr~=SUB"
+        tree("formatSub: expr~=SUB")
+      -- assume args.1 is the expression and args.2 is its subscript
+      if #args < 2 then
+        if debug then sayTeX$Lisp concat("formatSub: num args=",_
+          string(#args)$String)$String
+        return tree(concat("formatSub: num args=",_
+          string(#args)$String)$String)
+      if #args > 2 then
+        if debug then sayTeX$Lisp concat("formatSub: num args=",_
+          string(#args)$String)$String
+        return buildSubscript(formatHtml(first args,opPrec),_
+          newNodes("",[formatHtml(e,opPrec) for e in rest args]))
+      buildSubscript(formatHtml(first args,opPrec),_
+        formatHtml(args.2,opPrec))
+
+    formatFunction(op : Tree S, args : L E, prec : I) : Tree S ==
+      if debug then sayTeX$Lisp "formatFunction: " concat ["args=",_
+        argsToString(args)," prec=",string(prec)$S]
+      newNodes("",[op,tree("("),formatNary(",",args,minPrec),tree(")")])
+
+    formatNullary(op : S) : Tree S ==
+      if debug then sayTeX$Lisp "formatNullary: " concat ["op=",op]
+      op = "NOTHING" => empty()$Tree(S)
+      tree(op"()")
+
+    -- implement operation with single argument
+    -- an example is minus '-'
+    -- prec is precidence of operator, used to force brackets where
+    -- more tightly bound operation is next to less tightly bound operation
+    formatUnary(op : S, arg : E, prec : I) : Tree S ==
+      if debug then sayTeX$Lisp "formatUnary: " concat ["op=",op," arg=",_
+        stringify arg," prec=",string(prec)$S]
+      p : I := position(op,unaryOps)
+      p < 1 => error "unknown unary op"
+      opPrec := unaryPrecs.p
+      s : Tree S := newNodes("",[tree(op),formatHtml(arg,opPrec)])
+      opPrec < prec => newNodes("",[tree("("),s,tree(")")])
+      s
+
+    -- output division with numerator above the denominator
+    -- implemented as a table
+    buildOver(top : Tree S,bottom : Tree S) : Tree S ==
+      if debug then sayTeX$Lisp "buildOver"
+      topCell:Tree S := newNode("td",top)
+      bottomCell:Tree S := newNode("td style='border-top-style:solid'",_
+        bottom)
+      rows:(List Tree S) := [newNode("tr id='col'",topCell),_
+        newNode("tr id='col'",bottomCell)]
+      newNodes("table border='0' id='col'",rows)
+
+    -- op may be: "|","^","/","OVER","+->"
+    -- note: "+" and "*" are n-ary ops
+    formatBinary(op : S, args : L E, prec : I) : Tree S ==
+      if debug then sayTeX$Lisp "formatBinary: " concat ["op=",op,_
+        " args=",argsToString(args)," prec=",string(prec)$S]
+      p : I := position(op,binaryOps)
+      p < 1 => error "unknown binary op"
+      opPrec := binaryPrecs.p
+      -- if base op is product or sum need to add parentheses
+      if ATOM(first args)$Lisp@Boolean then
+        opa:S := stringify first args
+      else
+        la : L E := (first args pretend L E)
+        opa : S := stringify first la
+      if (opa = "SIGMA" or opa = "SIGMA2" or opa = "PI" or opa = "PI2")_
+        and op = "^" then
+          s1 : Tree S := newNodes("",[tree("("),formatHtml(first args,_
+            opPrec),tree(")")])
+      else
+        s1 : Tree S := formatHtml(first args, opPrec)
+      s2 : Tree S := formatHtml(first rest args, opPrec)
+      op = "|" => newNodes("",[s1,tree(op),s2])
+      op = "^" => buildSuperscript(s1,s2)
+      op = "/" => newNodes("",[s1,tree(op),s2])
+      op = "OVER" => buildOver(s1,s2)
+      op = "+->" => newNodes("",[s1,tree("|&mdash;&rsaquo;"),s2])
+      newNodes("",[s1,tree(op),s2])
+
+    -- build a zag from a table with a right part and a
+    -- upper and lower left part
+    buildZag(top:Tree S,lowerLeft:Tree S,lowerRight:Tree S) : Tree S ==
+      if debug then sayTeX$Lisp "buildZag"
+      cellTop:Tree S := _
+        newNode("td colspan='2' id='zag' style='border-bottom-style:solid'",_
+         top)
+      cellLowerLeft:Tree S := newNodes("td id='zag'",[lowerLeft,tree("+")])
+      cellLowerRight:Tree S := newNode("td id='zag'",lowerRight)
+      row1:Tree S := newNodes("tr id='zag'",[cellTop])
+      row2:Tree S := newNodes("tr id='zag'",[cellLowerLeft,cellLowerRight])
+      newNodes("table border='0' id='zag'",[row1,row2])
+
+    formatZag(args : L E,nestLevel:I)  : Tree S ==
+      -- args will be a list of things like this {{ZAG}{1}{7}}, the ZAG
+      -- must be there, the '1' and '7' could conceivably be more complex
+      -- expressions
+      --
+      -- ex 1. continuedFraction(314159/100000)
+      -- {{+}{3}{{ZAG}{1}{7}}{{ZAG}{1}{15}}{{ZAG}{1}{1}}{{ZAG}{1}{25}}
+      -- {{ZAG}{1}{1}}{{ZAG}{1}{7}}{{ZAG}{1}{4}}}
+      -- this is the preconditioned output form
+      -- including "op", the args list would be the rest of this
+      -- i.e op = '+' and args = {{3}{{ZAG}{1}{7}}{{ZAG}{1}{15}}
+      -- {{ZAG}{1}{1}}{{ZAG}{1}{25}}{{ZAG}{1}{1}}{{ZAG}{1}{7}}{{ZAG}{1}{4}}}
+      --
+      -- ex 2. continuedFraction(14159/100000)
+      -- this one doesn't have the leading integer
+      -- {{+}{{ZAG}{1}{7}}{{ZAG}{1}{15}}{{ZAG}{1}{1}}{{ZAG}{1}{25}}
+      -- {{ZAG}{1}{1}}{{ZAG}{1}{7}}{{ZAG}{1}{4}}}
+      --
+      -- ex 3. continuedFraction(3,repeating [1], repeating [3,6])
+      -- {{+}{3}{{ZAG}{1}{3}}{{ZAG}{1}{6}}{{ZAG}{1}{3}}{{ZAG}{1}{6}}
+      -- {{ZAG}{1}{3}}{{ZAG}{1}{6}}{{ZAG}{1}{3}}{{ZAG}{1}{6}}
+      -- {{ZAG}{1}{3}}{{ZAG}{1}{6}}{...}}
+      --
+      -- In each of these examples the args list consists of the terms
+      -- following the '+' op
+      -- so the first arg could be a "ZAG" or something
+      -- else, but the second arg looks like it has to be "ZAG", so maybe
+      -- test for #args > 1 and args.2 contains "ZAG".
+      -- Note that since the resulting tables are nested we need
+      -- to handle the whole continued fraction at once, i.e. we can't
+      -- just look for, e.g., {{ZAG}{1}{6}}
+      --
+      -- we will assume that the font starts at 16px and reduce it by 4
+      -- <span style='font-size:16px'>outer zag</span>
+      -- <span style='font-size:14px'>next zag</span>
+      -- <span style='font-size:12px'>next zag</span>
+      -- <span style='font-size:10px'>next zag</span>
+      -- <span style='font-size:9px'>lowest zag</span>
+      if debug then sayTeX$Lisp "formatZag: " concat ["args=",_
+        argsToString(args)]
+      tmpZag : L E := first args pretend L E
+      fontAttrib : S :=
+        nestLevel < 2 => "span style='font-size:16px'"
+        nestLevel = 2 => "span style='font-size:14px'"
+        nestLevel = 3 => "span style='font-size:12px'"
+        nestLevel = 4 => "span style='font-size:10px'"
+        "span style='font-size:9px'"
+      -- may want to test that tmpZag contains 'ZAG'
+      #args > 1 =>
+        newNode(fontAttrib,buildZag(formatHtml(first rest tmpZag,minPrec),_
+          formatHtml(first rest rest tmpZag,minPrec),_
+            formatZag(rest args,nestLevel+1)))
+      (first args = "...":: E)@Boolean => tree("&#x2026;")
+      op:S := stringify first args
+      position("ZAG",op,1) > 0 =>
+        newNode(fontAttrib,buildOver(formatHtml(first rest tmpZag,minPrec),_
+          formatHtml(first rest rest tmpZag,minPrec)))
+      tree("formatZag: Last argument in ZAG construct unknown operator: "op)
+
+    -- returns true if this term starts with a minus '-' sign
+    -- this is used so that we can suppress any plus '+' in front
+    -- of the - so we dont get terms like +-
+    neg?(arg : E) : Boolean ==
+      if debug then sayTeX$Lisp "neg?: " concat ["arg=",argsToString([arg])]
+      ATOM(arg)$Lisp@Boolean => false
+      l : L E := (arg pretend L E)
+      op : S := stringify first l
+      op = "-" => true
+      false
+
+    formatNary(op : S, args : L E, prec : I) : Tree S ==
+      if debug then sayTeX$Lisp "formatNary: " concat ["op=",op," args=",_
+        argsToString(args)," prec=",string(prec)$S]
+      formatNaryNoGroup(op, args, prec)
+
+    -- possible op values are:
+    -- ",",";","*"," ","ROW","+","-"
+    -- an example is content of matrix which gives:
+    -- {{ROW}{1}{2}}{{ROW}{3}{4}}
+    -- or AGGLST which gives op=, args={{1}{2}}
+    --
+    -- need to:
+    -- format ZAG
+    -- check for +-
+    -- add brackets for sigma or pi or root ("SIGMA","SIGMA2","PI","PI2")
+    formatNaryNoGroup(op : S, args : L E, prec : I)  : Tree S ==
+      if debug then sayTeX$Lisp "formatNaryNoGroup: " concat ["op=",op,_
+        " args=",argsToString(args)," prec=",string(prec)$S]
+      checkargs:Boolean := false
+      null args => empty()$Tree(S)
+      p : I := position(op,naryOps)
+      p < 1 => error "unknown nary op"
+      -- need to test for "ZAG" case and divert it here
+      (#args > 1) and (position("ZAG",stringify first rest args,1) > 0) =>
+           tmpS : S := stringify first args
+           position("ZAG",tmpS,1) > 0 => formatZag(args,1)
+           newNodes("",[formatHtml(first args,minPrec),tree("+"),_
+            formatZag(rest args,1)])
+      -- At least for the ops "*","+","-" we need to test to see if a
+      -- sigma or pi is one of their arguments because we might need
+      -- parentheses as indicated
+      -- by the problem with summation(operator(f)(i),i=1..n)+1 versus
+      -- summation(operator(f)(i)+1,i=1..n) having identical displays as of
+      -- 2007-12-21
+      l := empty()$Tree(S)
+      opPrec := naryPrecs.p
+      -- if checkargs is true check each arg except last one to see if it's
+      -- a sigma or pi and if so add parentheses. Other op's may have to be
+      -- checked for in future
+      count:I := 1
+      tags : (L Tree S)
+      if opPrec < prec then tags := [tree("("),formatHtml(args.1,opPrec)]
+      if opPrec >= prec then tags := [formatHtml(args.1,opPrec)]
+      for a in rest args repeat
+        if op ~= "+" or not neg?(a) then tags := append(tags,[tree(op)])
+        tags := append(tags,[formatHtml(a,opPrec)])
+      if opPrec < prec then tags := append(tags,[tree(")")])
+      newNodes("",tags)
+
+    -- expr is a tree structure
+    -- prec is the precision of integers
+    -- formatHtml returns a string for this node in the tree structure
+    -- and calls recursivly to evaluate sub expressions
+    formatHtml(arg : E,prec : I) : Tree S ==
+      if debug then sayTeX$Lisp "formatHtml: " concat ["arg=",_
+        argsToString([arg])," prec=",string(prec)$S]
+      i,len : Integer
+      intSplitLen : Integer := 20
+      ATOM(arg)$Lisp@Boolean =>
+        if debug then sayTeX$Lisp "formatHtml atom: " concat ["expr=",_
+          stringify arg," prec=",string(prec)$S]
+        str := stringify arg
+        (i := position(str,specialStrings)) > 0 =>
+          tree(specialStringsInHTML.i)
+        tree(str)
+      l : L E := (arg pretend L E)
+      null l => tree(blank)
+      op : S := stringify first l
+      args : L E := rest l
+      nargs : I := #args
+      -- need to test here in case first l is SUPERSUB case and then
+      -- pass first l and args to formatSuperSub.
+      position("SUPERSUB",op,1) > 0 =>
+        formatSuperSub(first l,args,minPrec)
+      -- now test for SUB
+      position("SUB",op,1) > 0 =>
+        formatSub(first l,args,minPrec)
+      -- special cases
+      -- specialOps are:
+      -- MATRIX, BRACKET, BRACE, CONCATB, VCONCAT
+      -- AGGLST, CONCAT, OVERBAR, ROOT, SUB, TAG
+      -- SUPERSUB, ZAG, AGGSET, SC, PAREN
+      -- SEGMENT, QUOTE, theMap, SLASH
+      member?(op, specialOps) => formatSpecial(op,args,prec)
+      -- specialOps are:
+      -- SIGMA, SIGMA2, PI, PI2, INTSIGN, INDEFINTEGRAL
+      member?(op, plexOps)    => formatPlex(op,args,prec)
+      -- nullary case: function with no aguments
+      0 = nargs => formatNullary op
+      -- unary case: function with one agument such as '-'
+      (1 = nargs) and member?(op, unaryOps) =>
+        formatUnary(op, first args, prec)
+      -- binary case
+      -- binary ops include special processing for | ^ / OVER and +->
+      (2 = nargs) and member?(op, binaryOps) =>
+        formatBinary(op, args, prec)
+      -- nary case: including '+' and '*'
+      member?(op,naryNGOps) => formatNaryNoGroup(op,args, prec)
+      member?(op,naryOps) => formatNary(op,args, prec)
+
+      op1 := formatHtml(first l,minPrec)
+      formatFunction(op1,args,prec)
+
+@
+<<HTMLFORM.dotabb>>=
+"HTMLFORM" [color="#88FF44",href="bookvol10.3.pdf#nameddest=HTMLFORM"]
+"STRING" [color="#4488FF",href="bookvol10.2.pdf#nameddest=STRING"]
+"HTMLFORM" -> "STRING"
+
+@
+%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 \section{domain HDP HomogeneousDirectProduct}
 
 <<HomogeneousDirectProduct.input>>=
@@ -149471,6 +150686,7 @@ Note that this code is not included in the generated catdef.spad file.
 <<domain HASHTBL HashTable>>
 <<domain HEAP Heap>>
 <<domain HEXADEC HexadecimalExpansion>>
+<<domain HTMLFORM HTMLFormat>>
 <<domain HDP HomogeneousDirectProduct>>
 <<domain HDMP HomogeneousDistributedMultivariatePolynomial>>
 <<domain HELLFDIV HyperellipticFiniteDivisor>>
diff --git a/books/bookvol5.pamphlet b/books/bookvol5.pamphlet
index 954e3af..ee58d0f 100644
--- a/books/bookvol5.pamphlet
+++ b/books/bookvol5.pamphlet
@@ -1019,7 +1019,7 @@ the Bill Burge's parser.
 <<defun ncIntLoop>>=
 (defun |ncIntLoop| ()
   (let ((curinstream *standard-output*)
-	(curoutstream *standard-input*))
+        (curoutstream *standard-input*))
     (declare (special curinstream curoutstream))
     (|intloop|)))
 
@@ -1346,16 +1346,16 @@ This function performs those setup commands.
 \calls{init-memory-config}{set-hole-size}
 <<defun init-memory-config>>=
 (defun init-memory-config (&key
-			   (cons 500)
-			   (fixnum 200)
-			   (symbol 500)
-			   (package 8)
-			   (array 400)
-			   (string 500)
-			   (cfun 100)
-			   (cpages 3000)
-			   (rpages 1000)
-			   (hole 2000) )
+                           (cons 500)
+                           (fixnum 200)
+                           (symbol 500)
+                           (package 8)
+                           (array 400)
+                           (string 500)
+                           (cfun 100)
+                           (cpages 3000)
+                           (rpages 1000)
+                           (hole 2000) )
   ;; initialize AKCL memory allocation parameters
   #+:AKCL
   (progn
@@ -1625,7 +1625,7 @@ $current-directory = "/research/test/"
   (setq $library-directory-list
    (mapcar #'make-absolute-filename $relative-library-directory-list))
   (setq |$defaultMsgDatabaseName|
-	(pathname (make-absolute-filename "/doc/msgs/s2-us.msgs")))
+        (pathname (make-absolute-filename "/doc/msgs/s2-us.msgs")))
   (setq |$msgDatabaseName| ())
   (setq $current-directory $spadroot))
 
@@ -14273,33 +14273,33 @@ the text in the buffer.  In the description of the keys below, ^n means
 Control-n, or holding the CONTROL key down while pressing "n".  Errors
 will ring the terminal bell.
 
-^A/^E	: Move cursor to beginning/end of the line.
+^A/^E   : Move cursor to beginning/end of the line.
 ^F/^B   : Move cursor forward/backward one character.
-^D	: Delete the character under the cursor.
+^D      : Delete the character under the cursor.
 ^H, DEL : Delete the character to the left of the cursor.
-^K	: Kill from the cursor to the end of line.
-^L	: Redraw current line.
-^O	: Toggle overwrite/insert mode. Initially in insert mode. Text
-	  added in overwrite mode (including yanks) overwrite
-	  existing text, while insert mode does not overwrite.
+^K      : Kill from the cursor to the end of line.
+^L      : Redraw current line.
+^O      : Toggle overwrite/insert mode. Initially in insert mode. Text
+          added in overwrite mode (including yanks) overwrite
+          existing text, while insert mode does not overwrite.
 ^P/^N   : Move to previous/next item on history list.
 ^R/^S   : Perform incremental reverse/forward search for string on
-	  the history list.  Typing normal characters adds to the current
-	  search string and searches for a match. Typing ^R/^S marks
-	  the start of a new search, and moves on to the next match.
-	  Typing ^H or DEL deletes the last character from the search 
-	  string, and searches from the starting location of the last search.  
-	  Therefore, repeated DEL's appear to unwind to the match nearest 
-	  the point at which the last ^R or ^S was typed.  If DEL is 
-	  repeated until the search string is empty the search location 
-	  begins from the start of the history list.  Typing ESC or 
-	  any other editing character accepts the current match and 
-	  loads it into the buffer, terminating the search.
-^T	: Toggle the characters under and to the left of the cursor.
-^Y	: Yank previously killed text back at current location.  Note that
-	  this will overwrite or insert, depending on the current mode.
+          the history list.  Typing normal characters adds to the current
+          search string and searches for a match. Typing ^R/^S marks
+          the start of a new search, and moves on to the next match.
+          Typing ^H or DEL deletes the last character from the search 
+          string, and searches from the starting location of the last search.  
+          Therefore, repeated DEL's appear to unwind to the match nearest 
+          the point at which the last ^R or ^S was typed.  If DEL is 
+          repeated until the search string is empty the search location 
+          begins from the start of the history list.  Typing ESC or 
+          any other editing character accepts the current match and 
+          loads it into the buffer, terminating the search.
+^T      : Toggle the characters under and to the left of the cursor.
+^Y      : Yank previously killed text back at current location.  Note that
+          this will overwrite or insert, depending on the current mode.
 ^U      : Show help (this text).
-TAB	: Perform command completion based on word to the left of the cursor. 
+TAB     : Perform command completion based on word to the left of the cursor. 
           Words are deemed to contain only the alphanumeric and the % ! ? _  
           characters.
 NL, CR  : returns current buffer to the program.
@@ -15557,44 +15557,43 @@ See:\\
 (eval-when (eval load)
  (setq |$systemCommands|
  '(
-   (|abbreviations|		     . |compiler|   )
-   (|boot|			     . |development|)
+   (|abbreviations|                  . |compiler|   )
+   (|boot|                           . |development|)
    (|browse|                         . |development|)
-   (|cd|			     . |interpreter|)
-   (|clear|			     . |interpreter|)
-   (|close|			     . |interpreter|)
-   (|compiler|			     . |compiler|   )
-   (|copyright|			     . |interpreter|)
-   (|credits|			     . |interpreter|)
-   (|describe|			     . |interpreter|)
-   (|display|			     . |interpreter|)
-   (|edit|			     . |interpreter|)
-   (|fin|			     . |development|)
-   (|frame|			     . |interpreter|)
-   (|help|			     . |interpreter|)
-   (|history|			     . |interpreter|)
-;; (|input|			     . |interpreter|)
-   (|lisp|			     . |development|)
-   (|library|			     . |interpreter|)
-   (|load|			     . |interpreter|)
-   (|ltrace|			     . |interpreter|)
-   (|pquit|			     . |interpreter|)
-   (|quit|			     . |interpreter|)
-   (|read|			     . |interpreter|)
-   (|savesystem|		     . |interpreter|)
-   (|set|			     . |interpreter|)
-   (|show|			     . |interpreter|)
-   (|spool|			     . |interpreter|)
-   (|summary|			     . |interpreter|)
-   (|synonym|			     . |interpreter|)
-   (|system|			     . |interpreter|)
-   (|trace|			     . |interpreter|)
-   (|trademark|			     . |interpreter|)
-   (|undo|			     . |interpreter|)
-   (|what|			     . |interpreter|)
-   (|with|			     . |interpreter|)
-   (|workfiles|			     . |development|)
-   (|zsystemdevelopment| . |interpreter|)
+   (|cd|                             . |interpreter|)
+   (|clear|                          . |interpreter|)
+   (|close|                          . |interpreter|)
+   (|compiler|                       . |compiler|   )
+   (|copyright|                      . |interpreter|)
+   (|credits|                        . |interpreter|)
+   (|describe|                       . |interpreter|)
+   (|display|                        . |interpreter|)
+   (|edit|                           . |interpreter|)
+   (|fin|                            . |development|)
+   (|frame|                          . |interpreter|)
+   (|help|                           . |interpreter|)
+   (|history|                        . |interpreter|)
+   (|lisp|                           . |development|)
+   (|library|                        . |interpreter|)
+   (|load|                           . |interpreter|)
+   (|ltrace|                         . |interpreter|)
+   (|pquit|                          . |interpreter|)
+   (|quit|                           . |interpreter|)
+   (|read|                           . |interpreter|)
+   (|savesystem|                     . |interpreter|)
+   (|set|                            . |interpreter|)
+   (|show|                           . |interpreter|)
+   (|spool|                          . |interpreter|)
+   (|summary|                        . |interpreter|)
+   (|synonym|                        . |interpreter|)
+   (|system|                         . |interpreter|)
+   (|trace|                          . |interpreter|)
+   (|trademark|                      . |interpreter|)
+   (|undo|                           . |interpreter|)
+   (|what|                           . |interpreter|)
+   (|with|                           . |interpreter|)
+   (|workfiles|                      . |development|)
+   (|zsystemdevelopment|             . |interpreter|)
  )))
 
 @
@@ -16923,55 +16922,55 @@ of synonyms which are in common use.
 (eval-when (eval load)
  (setq |$InitialCommandSynonymAlist|
    '(
-       (|?|	     . "what commands")
-       (|ap|	     . "what things")
-       (|apr|	     . "what things")
+       (|?|          . "what commands")
+       (|ap|         . "what things")
+       (|apr|        . "what things")
        (|apropos|    . "what things")
-       (|cache|	     . "set functions cache")
-       (|cl|	     . "clear")
-       (|cls|	     . "zsystemdevelopment )cls")
-       (|cms|	     . "system")
-       (|co|	     . "compiler")
-       (|d|	     . "display")
-       (|dep|	     . "display dependents")
+       (|cache|      . "set functions cache")
+       (|cl|         . "clear")
+       (|cls|        . "zsystemdevelopment )cls")
+       (|cms|        . "system")
+       (|co|         . "compiler")
+       (|d|          . "display")
+       (|dep|        . "display dependents")
        (|dependents| . "display dependents")
-       (|e|	     . "edit")
+       (|e|          . "edit")
        (|expose|     . "set expose add constructor")
-       (|fc|	     . "zsystemdevelopment )c")
-       (|fd|	     . "zsystemdevelopment )d")
-       (|fdt|	     . "zsystemdevelopment )dt")
-       (|fct|	     . "zsystemdevelopment )ct")
-       (|fctl|	     . "zsystemdevelopment )ctl")
-       (|fe|	     . "zsystemdevelopment )e")
-       (|fec|	     . "zsystemdevelopment )ec")
-       (|fect|	     . "zsystemdevelopment )ect")
-       (|fns|	     . "exec spadfn")
+       (|fc|         . "zsystemdevelopment )c")
+       (|fd|         . "zsystemdevelopment )d")
+       (|fdt|        . "zsystemdevelopment )dt")
+       (|fct|        . "zsystemdevelopment )ct")
+       (|fctl|       . "zsystemdevelopment )ctl")
+       (|fe|         . "zsystemdevelopment )e")
+       (|fec|        . "zsystemdevelopment )ec")
+       (|fect|       . "zsystemdevelopment )ect")
+       (|fns|        . "exec spadfn")
        (|fortran|    . "set output fortran")
-       (|h|	     . "help")
-       (|hd|	     . "system hypertex &")
-       (|kclam|	     . "boot clearClams ( )")
+       (|h|          . "help")
+       (|hd|         . "system hypertex &")
+       (|kclam|      . "boot clearClams ( )")
        (|killcaches| . "boot clearConstructorAndLisplibCaches ( )")
-       (|patch|	     . "zsystemdevelopment )patch")
-       (|pause|	     . "zsystemdevelopment )pause")
+       (|patch|      . "zsystemdevelopment )patch")
+       (|pause|      . "zsystemdevelopment )pause")
        (|prompt|     . "set message prompt")
        (|recurrence| . "set functions recurrence")
        (|restore|    . "history )restore")
-       (|save|	     . "history )save")
+       (|save|       . "history )save")
        (|startGraphics|    .  "system $AXIOM/lib/viewman &")
        (|startNAGLink|     .  "system $AXIOM/lib/nagman &")
        (|stopGraphics|     .  "lisp (|sockSendSignal| 2 15)")
        (|stopNAGLink|      .  "lisp (|sockSendSignal| 8 15)")
-       (|time|	     . "set message time")
-       (|type|	     . "set message type")
+       (|time|       . "set message time")
+       (|type|       . "set message type")
        (|unexpose|   . "set expose drop constructor")
-       (|up|	     . "zsystemdevelopment )update")
+       (|up|         . "zsystemdevelopment )update")
        (|version|    . "lisp (axiomVersion)")
-       (|w|	     . "what")
-       (|wc|	     . "what categories")
-       (|wd|	     . "what domains")
+       (|w|          . "what")
+       (|wc|         . "what categories")
+       (|wd|         . "what domains")
        (|who|        . "lisp (pprint credits)")
-       (|wp|	     . "what packages")
-       (|ws|	     . "what synonyms")
+       (|wp|         . "what packages")
+       (|ws|         . "what synonyms")
 )))
 
 @
@@ -22941,7 +22940,7 @@ o )history
  (declare (special /editfile))
   (setq /editfile l)
   (cond
-    (q	(/rq))
+    (q (/rq))
     (t (/rf)) )
   (flag |boot-NewKEY| 'key)
   (|terminateSystemCommand|)
@@ -23556,7 +23555,7 @@ args         arguments for compiling AXIOM code
        |setOutputLibrary|
        NIL
        |htSetOutputLibrary|
-	)
+       )
 @
 \section{Variables Used}
 \section{Functions}
@@ -23996,6 +23995,7 @@ otherwise the new algebra won't be loaded by the interpreter when needed.
    (|HallBasis| . HB)
    (|Heap| . HEAP)
    (|HexadecimalExpansion| . HEXADEC)
+   (|HTMLFormat| . HTMLFORM)
    (|IdealDecompositionPackage| . IDECOMP)
    (|IndexCard| . ICARD)
    (|InfClsPt| . ICP)
@@ -27691,8 +27691,9 @@ algebra     display output in algebraic form         On:CONSOLE
 characters  choose special output character set      plain 
 fortran     create output in FORTRAN format          Off:CONSOLE 
 fraction    how fractions are formatted              vertical 
+html        create output in HTML style              Off:CONSOLE 
 length      line length of output displays           77 
-mathml	    create output in MathML style	     Off:CONSOLE 
+mathml      create output in MathML style            Off:CONSOLE 
 openmath    create output in OpenMath style          Off:CONSOLE
 script      display output in SCRIPT formula format  Off:CONSOLE 
 scripts     show subscripts,... linearly             off 
@@ -27713,6 +27714,7 @@ is defined within the output structure.
 <<outputcharacters>>
 <<outputfortran>>
 <<outputfraction>>
+<<outputhtml>>
 <<outputlength>>
 <<outputmathml>>
 <<outputopenmath>>
@@ -28548,6 +28550,210 @@ The current setting is:  Off:CONSOLE
 
 @
 
+\subsection{html}
+\begin{verbatim}
+----------------------- The html Option ------------------------
+
+ Description: create output in html style
+
+ )set output html is used to tell AXIOM to turn html-style output
+printing on and off, and where to place the output.  By default,
+the destination for the output is the screen but printing is 
+turned off.
+
+Syntax:   )set output html <arg>
+    where arg can be one of
+  on          turn html printing on
+  off         turn html printing off (default state)
+  console     send html output to screen (default state)
+  fp<.fe>     send html output to file with file prefix fp
+              and file extension .fe. If not given, 
+              .fe defaults to .html.
+
+If you wish to send the output to a file, you must issue 
+this command twice: once with on and once with the file name. 
+For example, to send MathML output to the file polymer.html, 
+issue the two commands
+
+  )set output html on
+  )set output html polymer
+
+The output is placed in the directory from which you invoked 
+Axiom or the one you set with the )cd system command.
+The current setting is:  Off:CONSOLE 
+\end{verbatim}
+\defdollar{htmlFormat}
+<<initvars>>=
+(defvar |$htmlFormat| nil "create output in HTML format")
+
+@
+\defdollar{htmlOutputFile}
+<<initvars>>=
+(defvar |$htmlOutputFile| "CONSOLE" 
+   "where HTML output goes (enter {\em console} or a pathname)")
+
+@
+<<outputhtml>>=
+     (|html|
+      "create output in HTML style"
+      |interpreter|
+      FUNCTION
+      |setOutputHtml|
+      (("create output in HTML format"
+        LITERALS
+        |$htmlFormat|
+        (|off| |on|)
+        |off|)
+       (|break| |$htmlFormat|)
+       ("where HTML output goes (enter {\em console} or a pathname)"
+        FILENAME
+        |$htmlOutputFile|
+        |chkOutputFileName|
+        "console"))
+      NIL)
+
+@
+
+\defun{setOutputHtml}{setOutputHtml}
+\calls{setOutputHtml}{defiostream}
+\calls{setOutputHtml}{concat}
+\calls{setOutputHtml}{describeSetOutputHtml}
+\calls{setOutputHtml}{pairp}
+\calls{setOutputHtml}{qcdr}
+\calls{setOutputHtml}{qcar}
+\calls{setOutputHtml}{member}
+\calls{setOutputHtml}{upcase}
+\calls{setOutputHtml}{sayKeyedMsg}
+\calls{setOutputHtml}{shut}
+\calls{setOutputHtml}{pathnameType}
+\calls{setOutputHtml}{pathnameDirectory}
+\calls{setOutputHtml}{pathnameName}
+\callsdollar{setOutputHtml}{filep}
+\calls{setOutputHtml}{make-outstream}
+\calls{setOutputHtml}{object2String}
+\usesdollar{setOutputHtml}{htmlOutputStream}
+\usesdollar{setOutputHtml}{htmlOutputFile}
+\usesdollar{setOutputHtml}{htmlFormat}
+\usesdollar{setOutputHtml}{filep}
+<<defun setOutputHtml>>=
+(defun |setOutputHtml| (arg)
+ (let (label tmp1 tmp2 ptype fn ft fm filename teststream)
+ (declare (special |$htmlOutputStream| |$htmlOutputFile| |$htmlFormat|
+           $filep))
+   (cond
+    ((eq arg '|%initialize%|)
+     (setq |$htmlOutputStream|
+      (defiostream '((mode . output) (device . console)) 255 0))
+     (setq |$htmlOutputFile| "CONSOLE")
+     (setq |$htmlFormat| nil))
+    ((eq arg '|%display%|)
+     (if |$htmlFormat| 
+      (setq label "On:")
+      (setq label "Off:"))
+     (concat label |$htmlOutputFile|))
+    ((or (null arg) (eq arg '|%describe%|) (eq (car arg) '?))
+     (|describeSetOutputHtml|))
+    (t
+     (cond
+      ((and (pairp arg) 
+            (eq (qcdr arg) nil)
+            (progn (setq fn (qcar arg)) t)
+            (|member| fn '(y n ye yes no o on of off console 
+                   |y| |n| |ye| |yes| |no| |o| |on| |of| |off| |console|)))
+        '|ok|)
+      (t (setq arg (list fn '|smml|))))
+     (cond
+      ((and (pairp arg) 
+            (eq (qcdr arg) nil)
+            (progn (setq fn (qcar arg)) t))
+       (cond
+        ((|member| (upcase fn) '(y n ye o of))
+         (|sayKeyedMsg| 's2iv0002 '(|HTML| |html|)))
+        ((|member| (upcase fn) '(no off)) (setq |$htmlFormat| nil))
+        ((|member| (upcase fn) '(yes on)) (setq |$htmlFormat| t))
+        ((eq (upcase fn) 'console)
+         (shut |$htmlOutputStream|)
+         (setq |$htmlOutputStream|
+          (defiostream '((mode . output) (device . console)) 255 0))
+         (setq |$htmlOutputFile| "CONSOLE"))))
+      ((or 
+        (and (pairp arg)
+             (progn
+              (setq fn (qcar arg))
+              (setq tmp1 (qcdr arg))
+              (and (pairp tmp1)
+                   (eq (qcdr tmp1) nil)
+                   (progn (setq ft (qcar tmp1)) t))))
+        (and (pairp arg)
+             (progn (setq fn (qcar arg))
+                    (setq tmp1 (qcdr arg))
+                    (and (pairp tmp1)
+                         (progn
+                          (setq ft (qcar tmp1))
+                          (setq tmp2 (qcdr tmp1))
+                          (and (pairp tmp2)
+                               (eq (qcdr tmp2) nil)
+                               (progn
+                                (setq fm (qcar tmp2))
+                                t)))))))
+          (when (setq ptype (|pathnameType| fn))
+           (setq fn 
+            (concat (|pathnameDirectory| fn) (|pathnameName| fn)))
+           (setq ft ptype))
+          (unless fm (setq fm 'a))
+          (setq filename ($filep fn ft fm))
+          (cond
+           ((null filename) (|sayKeyedMsg| 's2iv0003 (list fn ft fm)))
+           ((setq teststream (make-outstream filename 255 0))
+            (shut |$htmlOutputStream|)
+            (setq |$htmlOutputStream| teststream)
+            (setq |$htmlOutputFile| (|object2String| filename))
+            (|sayKeyedMsg| 's2iv0004 (list "HTML" |$htmlOutputFile|)))
+           (t (|sayKeyedMsg| 's2iv0003 (list fn ft fm)))))
+      (t 
+       (|sayKeyedMsg| 's2iv0005 nil)
+       (|describeSetOutputHtml|))))))) 
+
+@
+
+\defun{describeSetOutputHtml}{describeSetOutputHtml}
+\calls{describeSetOutputHtml}{sayBrightly}
+\calls{describeSetOutputHtml}{setOutputHtml}
+<<defun describeSetOutputHtml>>=
+(defun |describeSetOutputHtml| ()
+ (|sayBrightly| (LIST
+ '|%b| ")set output html"
+ '|%d| "is used to tell AXIOM to turn HTML-style output"
+ '|%l| "printing on and off, and where to place the output.  By default, the"
+ '|%l| "destination for the output is the screen but printing is turned off."
+ '|%l|
+ '|%l| "Syntax:   )set output html <arg>"
+ '|%l| "    where arg can be one of"
+ '|%l| "  on          turn HTML printing on"
+ '|%l| "  off         turn HTML printing off (default state)"
+ '|%l| "  console     send HTML output to screen (default state)"
+ '|%l| "  fp<.fe>     send HTML output to file with file prefix fp and file"
+ '|%l| "              extension .fe. If not given, .fe defaults to .stex."
+ '|%l|
+ '|%l| "If you wish to send the output to a file, you must issue this command"
+ '|%l| "twice: once with"
+ '|%b| "on"
+ '|%d| "and once with the file name. For example, to send"
+ '|%l| "HTML output to the file"
+ '|%b| "polymer.smml,"
+ '|%d| "issue the two commands"
+ '|%l|
+ '|%l| "  )set output html on"
+ '|%l| "  )set output html polymer"
+ '|%l|
+ '|%l| "The output is placed in the directory from which you invoked AXIOM or"
+ '|%l| "the one you set with the )cd system command."
+ '|%l| "The current setting is: "
+ '|%b| (|setOutputHtml| '|%display%|)
+ '|%d|)))
+
+@
+
 \subsection{openmath}
 \begin{verbatim}
 ----------------------- The openmath Option ------------------------
@@ -34770,43 +34976,43 @@ o )library
                  (file-closed nil) (/editfile *spad-input-file*)
                 (|$noSubsumption| |$noSubsumption|) in-stream out-stream)
   (declare (special echo-meta /editfile *comp370-apply* *eof*
-		    file-closed xcape |$noSubsumption| |$InteractiveFrame|
+                    file-closed xcape |$noSubsumption| |$InteractiveFrame|
                     |$InteractiveMode| |$InitialDomainsInScope|))
   ;; only rebind |$InteractiveFrame| if compiling
   (progv (if (not |$InteractiveMode|) '(|$InteractiveFrame|))
-	 (if (not |$InteractiveMode|)
-	     (list (|addBinding| '|$DomainsInScope|
-		    `((fluid . |true|)
-		      (|special| . ,(copy-tree |$InitialDomainsInScope|)))
-		    (|addBinding| '|$Information| nil
+         (if (not |$InteractiveMode|)
+             (list (|addBinding| '|$DomainsInScope|
+                    `((fluid . |true|)
+                      (|special| . ,(copy-tree |$InitialDomainsInScope|)))
+                   (|addBinding| '|$Information| nil
                       (|makeInitialModemapFrame|)))))
   (init-boot/spad-reader)
   (unwind-protect
     (progn
       (setq in-stream (if *spad-input-file*
-			 (open *spad-input-file* :direction :input)
-			 *standard-input*))
+                        (open *spad-input-file* :direction :input)
+                         *standard-input*))
       (initialize-preparse in-stream)
       (setq out-stream (if *spad-output-file*
-			   (open *spad-output-file* :direction :output)
-			 *standard-output*))
+                        (open *spad-output-file* :direction :output)
+                         *standard-output*))
       (when *spad-output-file*
-	 (format out-stream "~&;;; -*- Mode:Lisp; Package:Boot  -*-~%~%")
-	 (print-package "BOOT"))
+         (format out-stream "~&;;; -*- Mode:Lisp; Package:Boot  -*-~%~%")
+         (print-package "BOOT"))
       (setq curoutstream out-stream)
       (loop
        (if (or *eof* file-closed) (return nil))
        (catch 'spad_reader
-	 (if (setq boot-line-stack (preparse in-stream))
-	     (let ((line (cdar boot-line-stack)))
-	       (declare (special line))
-	       (|PARSE-NewExpr|)
-	       (let ((parseout (pop-stack-1)) )
-		 (when parseout
-		       (let ((*standard-output* out-stream))
-			 (s-process parseout))
-		       (format out-stream "~&")))
-	       )))
+         (if (setq boot-line-stack (preparse in-stream))
+             (let ((line (cdar boot-line-stack)))
+               (declare (special line))
+               (|PARSE-NewExpr|)
+               (let ((parseout (pop-stack-1)) )
+                 (when parseout
+                       (let ((*standard-output* out-stream))
+                         (s-process parseout))
+                       (format out-stream "~&")))
+               )))
       (ioclear in-stream out-stream)))
     (if *spad-input-file* (shut in-stream))
     (if *spad-output-file* (shut out-stream)))
@@ -35278,7 +35484,7 @@ gets the index into the EBCDIC table, and returns the appropriate character.
                                            :direction :input)))))
          (if (and (numberp char-position) (> char-position 0))
            (file-position strm char-position))
-	   strm))))
+           strm))))
 
 @
 
@@ -35975,17 +36181,17 @@ Format of an entry in interp.daase:
   (constructor-name
     operationalist
     constructormodemap
-    modemaps		 -- this should not be needed. eliminate it.
-    object		 -- the name of the object file to load for this con.
+    modemaps            -- this should not be needed. eliminate it.
+    object              -- the name of the object file to load for this con.
     constructorcategory -- note that this info is the cadar of the
-	  constructormodemap for domains and packages so it is stored
-	  as NIL for them. it is valid for categories.
-    niladic		 -- t or nil directly
+          constructormodemap for domains and packages so it is stored
+          as NIL for them. it is valid for categories.
+    niladic             -- t or nil directly
     unused
-    cosig		 -- kept directly
-    constructorkind	 -- kept directly
-    defaultdomain	 -- a short list, for %i
-    ancestors		 -- used to compute new category updates
+    cosig                -- kept directly
+    constructorkind      -- kept directly
+    defaultdomain        -- a short list, for %i
+    ancestors            -- used to compute new category updates
   )
 \end{verbatim}
 \calls{interpOpen}{unsqueeze}
@@ -36380,7 +36586,7 @@ Format of an entry in browse.daase:
     (when (setq struct (get constructor 'database))
      (setq data (database-dependents struct))))
    (otherwise  (warn "~%(GETDATABASE ~a ~a) failed~%" constructor key)))
-  (when (numberp data)		       ;fetch the real data
+  (when (numberp data)      ;fetch the real data
    (when *miss* (format t "getdatabase miss: ~20a ~a~%" constructor key))
    (file-position stream data)
    (setq data (unsqueeze (read stream)))
@@ -36409,19 +36615,19 @@ Format of an entry in browse.daase:
    (case key ; fixup the special cases
     (sourcefile
      (when (and data (string= (directory-namestring data) "")
-	     (string= (pathname-type data) "spad"))
+             (string= (pathname-type data) "spad"))
       (setq data
        (concatenate 'string $spadroot "/../../src/algebra/" data))))
     (asharp?                               ; is this asharp code?
      (if (consp data)
       (setq data (cdr data))
       (setq data nil)))
-    (object				   ; fix up system object pathname
+    (object                                ; fix up system object pathname
      (if (consp data)
        (setq data
-	     (if (string= (directory-namestring (car data)) "")
-		 (concatenate 'string $spadroot "/algebra/" (car data) ".o")
-	       (car data)))
+             (if (string= (directory-namestring (car data)) "")
+                 (concatenate 'string $spadroot "/algebra/" (car data) ".o")
+               (car data)))
       (when (and data (string= (directory-namestring data) ""))
        (setq data (concatenate 'string $spadroot "/algebra/" data ".o")))))))
   data))
@@ -36494,7 +36700,7 @@ The localdatabase function tries to find files in the order of:
      (mapcan #'(lambda (f)
       (when (string-equal (pathname-type f) "nrlib")
        (list (concatenate 'string (namestring f) "/"
-			  vmlisp::*index-filename*)))) allfiles))))
+                          vmlisp::*index-filename*)))) allfiles))))
  (let (thisdir nrlibs object only dir key  (|$forceDatabaseUpdate| t) noexpose)
   (declare (special |$forceDatabaseUpdate| vmlisp::*index-filename*
                     |$ConstructorCache|))
@@ -36506,7 +36712,7 @@ The localdatabase function tries to find files in the order of:
   (when dir (setq nrlibs (processDir dir thisdir)))
   (dolist (file filelist)
    (let ((filename (pathname-name file))
-	 (namedir (directory-namestring file)))
+         (namedir (directory-namestring file)))
     (unless namedir (setq thisdir (concatenate 'string thisdir "/")))
     (cond
      ((setq file (probe-file
@@ -36563,7 +36769,7 @@ The localdatabase function tries to find files in the order of:
    (setq *allconstructors* (adjoin key *allconstructors*))
    (setf (get key 'database) dbstruct) ; store the struct, side-effect it...
    (setf (database-constructorform dbstruct) constructorform)
-   (setq *allOperations* nil)	; force this to recompute
+   (setq *allOperations* nil)   ; force this to recompute
    (setf (database-object dbstruct) object)
    (setq abbrev
      (intern (pathname-name (first (last (pathname-directory object))))))
@@ -36779,36 +36985,36 @@ constructor abbreviation to pamphlet file name.
   (dolist (con (|allConstructors|))
    (let (dbstruct)
      (when (setq dbstruct (get con 'database))
-	   (setf (database-cosig dbstruct)
-		 (cons nil (mapcar #'|categoryForm?|
-			   (cddar (database-constructormodemap dbstruct)))))
-	   (when (and (|categoryForm?| con)
-		      (= (length (setq d (|domainsOf| (list con) NIL NIL))) 1))
-		 (setq d (caar d))
-		 (when (= (length d) (length (|getConstructorForm| con)))
-	       (format t "   ~a has a default domain of ~a~%" con (car d))
-		       (setf (database-defaultdomain dbstruct) (car d)))))))
-	; note: genCategoryTable creates *ancestors-hash*. write-interpdb
-	; does gethash calls into it rather than doing a getdatabase call.
+           (setf (database-cosig dbstruct)
+                 (cons nil (mapcar #'|categoryForm?|
+                           (cddar (database-constructormodemap dbstruct)))))
+           (when (and (|categoryForm?| con)
+                      (= (length (setq d (|domainsOf| (list con) NIL NIL))) 1))
+                 (setq d (caar d))
+                 (when (= (length d) (length (|getConstructorForm| con)))
+               (format t "   ~a has a default domain of ~a~%" con (car d))
+                       (setf (database-defaultdomain dbstruct) (car d)))))))
+        ; note: genCategoryTable creates *ancestors-hash*. write-interpdb
+        ; does gethash calls into it rather than doing a getdatabase call.
   (write-interpdb)
   (write-warmdata)
   (when (probe-file (final-name "compress"))
-	(delete-file (final-name "compress")))
+        (delete-file (final-name "compress")))
   (rename-file "compress.build" (final-name "compress"))
   (when (probe-file (final-name "interp"))
-	(delete-file (final-name "interp")))
+        (delete-file (final-name "interp")))
   (rename-file "interp.build" (final-name "interp"))
   (when (probe-file (final-name "operation"))
-	(delete-file (final-name "operation")))
+        (delete-file (final-name "operation")))
   (rename-file "operation.build" (final-name "operation"))
   (when (probe-file (final-name "browse")) 
-	(delete-file (final-name "browse")))
+        (delete-file (final-name "browse")))
   (rename-file "browse.build" 
-	       (final-name "browse"))
+               (final-name "browse"))
   (when (probe-file (final-name "category"))
-	(delete-file (final-name "category")))
+        (delete-file (final-name "category")))
   (rename-file "category.build" 
-	       (final-name "category")))))
+               (final-name "category")))))
 
 @
 
@@ -36868,12 +37074,12 @@ short negative numbers.
 <<initvars>>=
 (defvar *attributes* 
       '(|nil| |infinite| |arbitraryExponent| |approximate| |complex|
-	|shallowMutable| |canonical| |noetherian| |central|
-	|partiallyOrderedSet| |arbitraryPrecision| |canonicalsClosed|
-	|noZeroDivisors| |rightUnitary| |leftUnitary|
-	|additiveValuation| |unitsKnown| |canonicalUnitNormal|
-	|multiplicativeValuation| |finiteAggregate| |shallowlyMutable|
-	|commutative|) "The list of known algebra attributes")
+        |shallowMutable| |canonical| |noetherian| |central|
+        |partiallyOrderedSet| |arbitraryPrecision| |canonicalsClosed|
+        |noZeroDivisors| |rightUnitary| |leftUnitary|
+        |additiveValuation| |unitsKnown| |canonicalUnitNormal|
+        |multiplicativeValuation| |finiteAggregate| |shallowlyMutable|
+        |commutative|) "The list of known algebra attributes")
 
 @
 
@@ -36893,7 +37099,7 @@ short negative numbers.
   (finish-output out)
   (setq masterpos (file-position out))
   (setq compresslist
-	(append (|allConstructors|) (|allOperations|) *attributes*))
+        (append (|allConstructors|) (|allOperations|) *attributes*))
   (push "algebra" compresslist)
   (push "failed" compresslist)
   (push 'signature compresslist)
@@ -36961,12 +37167,12 @@ using integers as indexes into the compression vector.
 (defun unsqueeze (expr)
  (declare (special *compressvector*))
   (cond ((atom expr)
-	 (cond ((and (numberp expr) (<= expr 0))
-		(svref *compressVector* (- expr)))
-	       (t expr)))
-	(t (rplaca expr (unsqueeze (car expr)))
-	   (rplacd expr (unsqueeze (cdr expr)))
-	   expr)))
+         (cond ((and (numberp expr) (<= expr 0))
+                (svref *compressVector* (- expr)))
+               (t expr)))
+        (t (rplaca expr (unsqueeze (car expr)))
+           (rplacd expr (unsqueeze (cdr expr)))
+           expr)))
 
 @
 
@@ -36976,17 +37182,17 @@ using integers as indexes into the compression vector.
   (constructor-name
     operationalist
     constructormodemap
-    modemaps		 -- this should not be needed. eliminate it.
-    object		 -- the name of the object file to load for this con.
+    modemaps             -- this should not be needed. eliminate it.
+    object               -- the name of the object file to load for this con.
     constructorcategory -- note that this info is the cadar of the
-	  constructormodemap for domains and packages so it is stored
-	  as NIL for them. it is valid for categories.
-    niladic		 -- t or nil directly
+          constructormodemap for domains and packages so it is stored
+          as NIL for them. it is valid for categories.
+    niladic              -- t or nil directly
     unused
-    cosig		 -- kept directly
-    constructorkind	 -- kept directly
-    defaultdomain	 -- a short list, for %i
-    ancestors		 -- used to compute new category updates
+    cosig                -- kept directly
+    constructorkind      -- kept directly
+    defaultdomain        -- a short list, for %i
+    ancestors            -- used to compute new category updates
   )
 \end{verbatim}
 
@@ -36997,8 +37203,8 @@ Here I'll try to outline the interp database write procedure
  "build interp.daase from hash tables"
  (declare (special $spadroot *ancestors-hash*))
  (let (opalistpos modemapspos cmodemappos master masterpos obj *print-pretty*
-	concategory categorypos kind niladic cosig abbrev defaultdomain
-	ancestors ancestorspos out)
+        concategory categorypos kind niladic cosig abbrev defaultdomain
+        ancestors ancestorspos out)
   (declare (special *print-pretty*))
   (print "building interp.daase")
 
@@ -37187,8 +37393,8 @@ Here I'll try to outline the interp database write procedure
  "build interp.daase from hash tables"
  (declare (special $spadroot *ancestors-hash*))
  (let (opalistpos modemapspos cmodemappos master masterpos obj *print-pretty*
-	concategory categorypos kind niladic cosig abbrev defaultdomain
-	ancestors ancestorspos out)
+        concategory categorypos kind niladic cosig abbrev defaultdomain
+        ancestors ancestorspos out)
   (declare (special *print-pretty*))
   (print "building interp.daase")
   (setq out (open "interp.build" :direction :output))
@@ -37866,9 +38072,9 @@ semantics survive.
 (defun bvec-greater (bv1 bv2)
   (let ((pos (mismatch bv1 bv2)))
     (cond ((or (null pos) (>= pos (length bv1))) nil)
-	  ((< pos (length bv2)) (> (bit bv1 pos) (bit bv2 pos)))
-	  ((find 1 bv1 :start pos) t)
-	  (t nil))))
+          ((< pos (length bv2)) (> (bit bv1 pos) (bit bv2 pos)))
+          ((find 1 bv1 :start pos) t)
+          (t nil))))
 
 @
 
@@ -39969,6 +40175,7 @@ This needs to work off the internal exposure list, not the file.
 <<defun describeSetOutputAlgebra>>
 <<defun describeSetOutputFormula>>
 <<defun describeSetOutputFortran>>
+<<defun describeSetOutputHtml>>
 <<defun describeSetOutputMathml>>
 <<defun describeSetOutputOpenMath>>
 <<defun describeSetOutputTex>>
@@ -41035,6 +41242,7 @@ This needs to work off the internal exposure list, not the file.
 <<defun setOutputFormula>>
 <<defun setOutputFortran>>
 <<defun setOutputLibrary>>
+<<defun setOutputHtml>>
 <<defun setOutputMathml>>
 <<defun setOutputOpenMath>>
 <<defun setOutputTex>>
diff --git a/books/bookvol7.1.pamphlet b/books/bookvol7.1.pamphlet
index b18f78b..37294f3 100644
--- a/books/bookvol7.1.pamphlet
+++ b/books/bookvol7.1.pamphlet
@@ -79058,6 +79058,8 @@ that the correct output is shown in the text.
     \menudownlink{{4.5. TeX Format}}{ugInOutTeXPage}
     \menudownlink{{4.6. IBM Script Formula Format}}{ugInOutScriptPage}
     \menudownlink{{4.7. FORTRAN Format}}{ugInOutFortranPage}
+    \menudownlink{{4.8. HTML Format}}{ugInOutHTMLPage}
+    \menudownlink{{4.9. MathML Format}}{ugInOutMathMLPage}
 \endmenu
 \endscroll
 \autobuttons
@@ -79204,6 +79206,8 @@ The names are
 \item[fortran]  for FORTRAN output.
 \item[algebra]  for monospace two-dimensional mathematical output.
 \item[tex]      for \texht{\TeX}{TeX} output.
+\item[html]     for HTML output.
+\item[mathml]   for MathML output.
 \item[script]   for IBM Script Formula Format output.
 \enditems
 \indent{0}
@@ -80063,6 +80067,46 @@ Look at the code generated for the matrix again.
 \end{paste}\end{patch}
 
 @
+\pagehead{ugInOutHTMLPage}{ug04.ht}{HTML Format}
+<<ug04.ht>>=
+\begin{page}{ugInOutHTMLPage}{4.8. HTML Format}
+\beginscroll
+
+Axiom can produce HTML output for your expressions.
+The output is produced by the HTMLFormat domain.
+
+To turn on HTML output formatting, issue this.
+
+)set output html on
+
+To turn HTML output formatting off, issue 
+
+)set output html off
+
+\endscroll
+\autobuttons
+\end{page}
+
+\pagehead{ugInOutMathMLPage}{ug04.ht}{MathML Format}
+<<ug04.ht>>=
+\begin{page}{ugInOutMathMLPage}{4.9. MathML Format}
+\beginscroll
+
+Axiom can produce MathML output for your expressions.
+The output is produced by the MathMLFormat domain.
+
+To turn on MathML output formatting, issue this.
+
+)set output mathml on
+
+To turn MathML output formatting off, issue 
+
+)set output mathml off
+
+\endscroll
+\autobuttons
+\end{page}
+
 \chapter{Users Guide Chapter 5 (ug05.ht)}
 \pagehead{ugLangPage}{ug05.ht}
 {Introduction to the Axiom Interactive Language}
diff --git a/books/ps/v103htmlformat.eps b/books/ps/v103htmlformat.eps
new file mode 100644
index 0000000..a582746
--- /dev/null
+++ b/books/ps/v103htmlformat.eps
@@ -0,0 +1,266 @@
+%!PS-Adobe-3.0 EPSF-3.0
+%%Creator: Graphviz version 2.20.2 (Mon Mar 30 10:09:11 UTC 2009)
+%%For: (root) root
+%%Title: pic
+%%Pages: 1
+%%BoundingBox: 36 36 140 152
+%%EndComments
+save
+%%BeginProlog
+/DotDict 200 dict def
+DotDict begin
+
+/setupLatin1 {
+mark
+/EncodingVector 256 array def
+ EncodingVector 0
+
+ISOLatin1Encoding 0 255 getinterval putinterval
+EncodingVector 45 /hyphen put
+
+% Set up ISO Latin 1 character encoding
+/starnetISO {
+        dup dup findfont dup length dict begin
+        { 1 index /FID ne { def }{ pop pop } ifelse
+        } forall
+        /Encoding EncodingVector def
+        currentdict end definefont
+} def
+/Times-Roman starnetISO def
+/Times-Italic starnetISO def
+/Times-Bold starnetISO def
+/Times-BoldItalic starnetISO def
+/Helvetica starnetISO def
+/Helvetica-Oblique starnetISO def
+/Helvetica-Bold starnetISO def
+/Helvetica-BoldOblique starnetISO def
+/Courier starnetISO def
+/Courier-Oblique starnetISO def
+/Courier-Bold starnetISO def
+/Courier-BoldOblique starnetISO def
+cleartomark
+} bind def
+
+%%BeginResource: procset graphviz 0 0
+/coord-font-family /Times-Roman def
+/default-font-family /Times-Roman def
+/coordfont coord-font-family findfont 8 scalefont def
+
+/InvScaleFactor 1.0 def
+/set_scale {
+       dup 1 exch div /InvScaleFactor exch def
+       scale
+} bind def
+
+% styles
+/solid { [] 0 setdash } bind def
+/dashed { [9 InvScaleFactor mul dup ] 0 setdash } bind def
+/dotted { [1 InvScaleFactor mul 6 InvScaleFactor mul] 0 setdash } bind def
+/invis {/fill {newpath} def /stroke {newpath} def /show {pop newpath} def} bind def
+/bold { 2 setlinewidth } bind def
+/filled { } bind def
+/unfilled { } bind def
+/rounded { } bind def
+/diagonals { } bind def
+
+% hooks for setting color 
+/nodecolor { sethsbcolor } bind def
+/edgecolor { sethsbcolor } bind def
+/graphcolor { sethsbcolor } bind def
+/nopcolor {pop pop pop} bind def
+
+/beginpage {	% i j npages
+	/npages exch def
+	/j exch def
+	/i exch def
+	/str 10 string def
+	npages 1 gt {
+		gsave
+			coordfont setfont
+			0 0 moveto
+			(\() show i str cvs show (,) show j str cvs show (\)) show
+		grestore
+	} if
+} bind def
+
+/set_font {
+	findfont exch
+	scalefont setfont
+} def
+
+% draw text fitted to its expected width
+/alignedtext {			% width text
+	/text exch def
+	/width exch def
+	gsave
+		width 0 gt {
+			[] 0 setdash
+			text stringwidth pop width exch sub text length div 0 text ashow
+		} if
+	grestore
+} def
+
+/boxprim {				% xcorner ycorner xsize ysize
+		4 2 roll
+		moveto
+		2 copy
+		exch 0 rlineto
+		0 exch rlineto
+		pop neg 0 rlineto
+		closepath
+} bind def
+
+/ellipse_path {
+	/ry exch def
+	/rx exch def
+	/y exch def
+	/x exch def
+	matrix currentmatrix
+	newpath
+	x y translate
+	rx ry scale
+	0 0 1 0 360 arc
+	setmatrix
+} bind def
+
+/endpage { showpage } bind def
+/showpage { } def
+
+/layercolorseq
+	[	% layer color sequence - darkest to lightest
+		[0 0 0]
+		[.2 .8 .8]
+		[.4 .8 .8]
+		[.6 .8 .8]
+		[.8 .8 .8]
+	]
+def
+
+/layerlen layercolorseq length def
+
+/setlayer {/maxlayer exch def /curlayer exch def
+	layercolorseq curlayer 1 sub layerlen mod get
+	aload pop sethsbcolor
+	/nodecolor {nopcolor} def
+	/edgecolor {nopcolor} def
+	/graphcolor {nopcolor} def
+} bind def
+
+/onlayer { curlayer ne {invis} if } def
+
+/onlayers {
+	/myupper exch def
+	/mylower exch def
+	curlayer mylower lt
+	curlayer myupper gt
+	or
+	{invis} if
+} def
+
+/curlayer 0 def
+
+%%EndResource
+%%EndProlog
+%%BeginSetup
+14 default-font-family set_font
+1 setmiterlimit
+% /arrowlength 10 def
+% /arrowwidth 5 def
+
+% make sure pdfmark is harmless for PS-interpreters other than Distiller
+/pdfmark where {pop} {userdict /pdfmark /cleartomark load put} ifelse
+% make '<<' and '>>' safe on PS Level 1 devices
+/languagelevel where {pop languagelevel}{1} ifelse
+2 lt {
+    userdict (<<) cvn ([) cvn load put
+    userdict (>>) cvn ([) cvn load put
+} if
+
+%%EndSetup
+setupLatin1
+%%Page: 1 1
+%%PageBoundingBox: 36 36 140 152
+%%PageOrientation: Portrait
+0 0 1 beginpage
+gsave
+36 36 104 116 boxprim clip newpath
+1 1 set_scale 0 rotate 40 40 translate
+% HTMLFORM
+gsave
+[ /Rect [ 0 72 96 108 ]
+  /Border [ 0 0 0 ]
+  /Action << /Subtype /URI /URI (bookvol10.3.pdf#nameddest=HTMLFORM) >>
+  /Subtype /Link
+/ANN pdfmark
+0.273 0.733 1.000 nodecolor
+newpath 96 108 moveto
+0 108 lineto
+0 72 lineto
+96 72 lineto
+closepath fill
+1 setlinewidth
+filled
+0.273 0.733 1.000 nodecolor
+newpath 96 108 moveto
+0 108 lineto
+0 72 lineto
+96 72 lineto
+closepath stroke
+0.000 0.000 0.000 nodecolor
+14 /Times-Roman set_font
+7.5 85.9 moveto 81 (HTMLFORM) alignedtext
+grestore
+% STRING
+gsave
+[ /Rect [ 13 0 83 36 ]
+  /Border [ 0 0 0 ]
+  /Action << /Subtype /URI /URI (bookvol10.2.pdf#nameddest=STRING) >>
+  /Subtype /Link
+/ANN pdfmark
+0.606 0.733 1.000 nodecolor
+newpath 83 36 moveto
+13 36 lineto
+13 0 lineto
+83 0 lineto
+closepath fill
+1 setlinewidth
+filled
+0.606 0.733 1.000 nodecolor
+newpath 83 36 moveto
+13 36 lineto
+13 0 lineto
+83 0 lineto
+closepath stroke
+0.000 0.000 0.000 nodecolor
+14 /Times-Roman set_font
+21 13.9 moveto 54 (STRING) alignedtext
+grestore
+% HTMLFORM->STRING
+gsave
+1 setlinewidth
+0.000 0.000 0.000 edgecolor
+newpath 48 72 moveto
+48 64 48 55 48 46 curveto
+stroke
+0.000 0.000 0.000 edgecolor
+newpath 51.5 46 moveto
+48 36 lineto
+44.5 46 lineto
+closepath fill
+1 setlinewidth
+solid
+0.000 0.000 0.000 edgecolor
+newpath 51.5 46 moveto
+48 36 lineto
+44.5 46 lineto
+closepath stroke
+grestore
+endpage
+showpage
+grestore
+%%PageTrailer
+%%EndPage: 1
+%%Trailer
+end
+restore
+%%EOF
diff --git a/changelog b/changelog
index 5c5221a..4552868 100644
--- a/changelog
+++ b/changelog
@@ -1,3 +1,11 @@
+20100706 myb src/axiom-website/patches.html 20100706.01.myb.patch
+20100706 myb src/interp/vmlisp.lisp HTMLFormat support code
+20100706 myb src/interp/i-output.lisp HTMLFormat support code
+20100706 myb src/algebra/Makefile test and help for HTMLFormat
+20100706 myb books/bookvol7.1 document HTMLFormat
+20100706 myb books/bookvol5 expose HTMLFormat, add support code
+20100706 myb books/bookvol10.3 add HTMLFormat
+20100706 myb books/ps/v103htmlformat.eps added
 20100705 wxh src/axiom-website/patches.html 20100705.01.wxh.patch
 20100705 wxh src/algebra/Makefile test and help ComplexDoubleFloatMatrix 
 20100705 wxh books/bookvol5 expose ComplexDoubleFloatMatrix, add macros
diff --git a/src/algebra/Makefile.pamphlet b/src/algebra/Makefile.pamphlet
index 3269146..0f325cf 100644
--- a/src/algebra/Makefile.pamphlet
+++ b/src/algebra/Makefile.pamphlet
@@ -5377,7 +5377,8 @@ LAYER11=\
   ${OUT}/GALFACTU.o ${OUT}/GALPOLYU.o ${OUT}/GB.o       ${OUT}/GBEUCLID.o \
   ${OUT}/GBF.o      ${OUT}/GBINTERN.o ${OUT}/GHENSEL.o  ${OUT}/GMODPOL.o  \
   ${OUT}/GOSPER.o   ${OUT}/GRIMAGE.o  ${OUT}/GROEBSOL.o ${OUT}/HDMP.o     \
-  ${OUT}/HDP.o      ${OUT}/HEXADEC.o  ${OUT}/HEUGCD.o   ${OUT}/IBPTOOLS.o \
+  ${OUT}/HDP.o      ${OUT}/HEXADEC.o  ${OUT}/HEUGCD.o   ${OUT}/HTMLFORM.o \
+  ${OUT}/IBPTOOLS.o \
   ${OUT}/IFF.o      ${OUT}/IBITS.o    ${OUT}/ICARD.o    ${OUT}/ICDEN.o    \
   ${OUT}/IDECOMP.o  ${OUT}/IIARRAY2.o ${OUT}/IMATLIN.o  ${OUT}/IMATQF.o   \
   ${OUT}/INMODGCD.o ${OUT}/INNMFACT.o ${OUT}/INPSIGN.o  ${OUT}/INTERGB.o  \
@@ -6871,6 +6872,21 @@ LAYER11=\
 /*"HEUGCD" -> {"ORDSET-"; "ABELSG-"; "SGROUP-"; "SETCAT-"; "RETRACT-"}*/
 /*"HEUGCD" -> "BASTYPE-"*/
 
+"HTMLFORM" [color="#88FF44",href="bookvol10.3.pdf#nameddest=HTMLFORM"]
+"HTMLFORM" -> "STRING"
+/*"HTMLFORM" -> {"SETCAT"; "BASTYPE"; "KOERCE"; "INT"; "NNI"; "STRICAT"}*/
+/*"HTMLFORM" -> {"SRAGG"; "A1AGG"; "FLAGG"; "LNAGG"; "IXAGG"; "HOAGG"; "AGG"}*/
+/*"HTMLFORM" -> {"TYPE"; "EVALAB"; "IEVALAB"; "ELTAGG"; "ELTAB"; "CLAGG"}*/
+/*"HTMLFORM" -> {"KONVERT"; "ORDSET"; "OM"; "RCAGG"; "BOOLEAN"; "CHAR"}*/
+/*"HTMLFORM" -> {"SINT"; "OUTFORM"; "LIST"; "PRIMARR"; "A1AGG-"; "ISTRING"}*/
+/*"HTMLFORM" -> {"SRAGG-"; "ILIST"; "LSAGG"; "STAGG"; "URAGG"; "ELAGG"}*/
+/*"HTMLFORM" -> {"LSAGG-"; "ORDFIN"; "FINITE"; "STAGG-"; "FLAGG-"; "LNAGG-"}*/
+/*"HTMLFORM" -> {"IXAGG-"; "CLAGG-"; "HOAGG-"; "ORDSET-"; "AGG-"; "ELTAGG-"}*/
+/*"HTMLFORM" -> {"SETCAT-"; "BASTYPE-"; "ELAGG-"; "URAGG-"; "INS-"; "PI"}*/
+/*"HTMLFORM" -> {"EUCDOM-"; "UFD-"; "GCDDOM-"; "INTDOM-"; "ALGEBRA-"}*/
+/*"HTMLFORM" -> {"DIFRING-"; "ORDRING-"; "MODULE-"; "RING-"; "ABELGRP-"}*/
+/*"HTMLFORM" -> {"ABELMON-"; "MONOID-"; "ABELSG-"; "SGROUP-"; "RETRACT-"}*/
+
 "IBPTOOLS" [color="#FF4488",href="bookvol10.4.pdf#nameddest=IBPTOOLS"]
 /*"IBPTOOLS" -> {"RING"; "RNG"; "ABELGRP"; "CABMON"; "ABELMON"; "ABELSG"}*/
 /*"IBPTOOLS" -> {"SETCAT"; "BASTYPE"; "KOERCE"; "SGROUP"; "MONOID"}*/
@@ -17530,6 +17546,7 @@ SPADHELP=\
  ${HELP}/HashTable.help \
  ${HELP}/Heap.help \
  ${HELP}/HexadecimalExpansion.help \
+ ${HELP}/HTMLFormat.help \
  ${HELP}/HomogeneousAggregate.help \
  ${HELP}/HomogeneousDirectProduct.help \
  ${HELP}/HomogeneousDistributedMultivariatePolynomial.help \
@@ -18221,6 +18238,7 @@ REGRESS= \
  HashTable.regress \
  Heap.regress \
  HexadecimalExpansion.regress \
+ HTMLFormat.regress \
  HomogeneousAggregate.regress \
  HomogeneousDirectProduct.regress \
  HomogeneousDistributedMultivariatePolynomial.regress \
@@ -21862,6 +21880,18 @@ ${HELP}/HexadecimalExpansion.help: ${BOOKS}/bookvol10.3.pamphlet
            ${BOOKS}/bookvol10.3.pamphlet >${INPUT}/HexadecimalExpansion.input
 	@echo "HexadecimalExpansion (HEXADEC)" >>${HELPFILE}
 
+${HELP}/HTMLFormat.help: ${BOOKS}/bookvol10.3.pamphlet
+	@echo 5000 create HTMLFormat.help from \
+           ${BOOKS}/bookvol10.3.pamphlet
+	@${TANGLE} -R"HTMLFormat.help" \
+           ${BOOKS}/bookvol10.3.pamphlet \
+           >${HELP}/HTMLFormat.help
+	@cp ${HELP}/HTMLFormat.help ${HELP}/HTMLFORM.help
+	@${TANGLE} -R"HTMLFormat.input" \
+            ${BOOKS}/bookvol10.3.pamphlet \
+            >${INPUT}/HTMLFormat.input
+	@echo "HTMLFormat (HTMLFORM)" >>${HELPFILE}
+
 ${HELP}/HomogeneousAggregate.help: ${BOOKS}/bookvol10.2.pamphlet
 	@echo 5000 create HomogeneousAggregate.help from \
            ${BOOKS}/bookvol10.2.pamphlet
diff --git a/src/axiom-website/patches.html b/src/axiom-website/patches.html
index 370e5e3..d5ef5a5 100644
--- a/src/axiom-website/patches.html
+++ b/src/axiom-website/patches.html
@@ -2982,5 +2982,7 @@ src/input/Makefile add TESTSET=notests<br/>
 books/bookvol10.3 add DoubleFloatMatrix<br/>
 <a href="patches/20100705.01.wxh.patch">20100705.01.wxh.patch</a>
 books/bookvol10.3 add ComplexDoubleFloatMatrix<br/>
+<a href="patches/20100706.01.myb.patch">20100706.01.myb.patch</a>
+books/bookvol10.3 add HTMLFormat<br/>
  </body>
 </html>
diff --git a/src/interp/i-output.lisp.pamphlet b/src/interp/i-output.lisp.pamphlet
index baac0a3..e2875b4 100644
--- a/src/interp/i-output.lisp.pamphlet
+++ b/src/interp/i-output.lisp.pamphlet
@@ -4156,6 +4156,20 @@ NIL
         (FORCE-OUTPUT |$mathmlOutputStream|)
         NIL))))
 
+(defun |htmlFormat| (expr)
+ "Output the expression using HTML format"
+ (let (ht htrep formatFn displayFn)
+ (declare (special |$htmlOutputStream| |$OutputForm|))
+  (setq ht '(|HTMLFormat|))
+  (setq htrep '(|String|))
+  (setq formatFn
+    (|getFunctionFromDomain| '|coerce| ht (cons |$OutputForm| nil)))
+  (setq displayFn (|getFunctionFromDomain| '|display| ht (cons htrep nil)))
+  (spadcall (spadcall expr formatFn) displayFn)
+  (terpri |$htmlOutputStream|)
+  (force-output |$htmlOutputStream|)
+  nil))
+
 ;output(expr,domain) ==
 ;  if isWrapped expr then expr := unwrap expr
 ;  isMapExpr expr =>
@@ -4194,17 +4208,19 @@ NIL
   (PROG (T$ |x| |printfun| |textwrit| |ISTMP#1| S)
     (DECLARE (SPECIAL |$mathmlFormat| |$texFormat| |$algebraFormat|
                       |$fortranOutputStream| |$collectOutput|
-                      |$fortranFormat| |$formulaFormat| |$OutputForm|))
+                      |$fortranFormat| |$formulaFormat| |$OutputForm|
+                      |$htmlFormat|))
     (RETURN
       (PROGN
         (COND
           ((|isWrapped| |expr|) (SPADLET |expr| (|unwrap| |expr|))))
         (COND
           ((|isMapExpr| |expr|)
-           (COND (|$formulaFormat| (|formulaFormat| |expr|)))
-           (COND (|$texFormat| (|texFormat| |expr|)))
-           (COND (|$algebraFormat| (|mathprintWithNumber| |expr|)))
-           (COND (|$mathmlFormat| (|mathmlFormat| |expr|)) ('T NIL)))
+           (when |$formulaFormat| (|formulaFormat| |expr|))
+           (when |$texFormat|     (|texFormat| |expr|))
+           (when |$algebraFormat| (|mathprintWithNumber| |expr|))
+           (when |$htmlFormat|    (|htmlFormat| |expr|))
+           (when |$mathmlFormat|  (|mathmlFormat| |expr|)))
           ((OR (|categoryForm?| |domain|)
                (|member| |domain|
                    '((|Mode|) (|Domain|) (|SubDomain| (|Domain|)))))
@@ -4227,9 +4243,10 @@ NIL
                    ((NULL |$collectOutput|)
                     (TERPRI |$fortranOutputStream|)))
                  (FORCE-OUTPUT |$fortranOutputStream|)))
-           (COND (|$algebraFormat| (|mathprintWithNumber| |x|)))
-           (COND (|$texFormat| (|texFormat| |x|)))
-           (COND (|$mathmlFormat| (|mathmlFormat| |x|)) ('T NIL)))
+           (when |$algebraFormat| (|mathprintWithNumber| |x|))
+           (when |$texFormat| (|texFormat| |x|))
+           (when |$htmlFormat| (|htmlFormat| |x|))
+           (when |$mathmlFormat| (|mathmlFormat| |x|)))
           ((AND (FUNCTIONP (|opOf| |domain|))
                 (NULL (SYMBOLP (|opOf| |domain|)))
                 (SPADLET |printfun|
diff --git a/src/interp/vmlisp.lisp.pamphlet b/src/interp/vmlisp.lisp.pamphlet
index a0822d5..24030f5 100644
--- a/src/interp/vmlisp.lisp.pamphlet
+++ b/src/interp/vmlisp.lisp.pamphlet
@@ -5698,6 +5698,9 @@ now the function is defined but does nothing.
 (defvar |$specialCaseKeyList| nil "checked in optCall")
 (defvar |$formulaFormat| nil "if true produce script formula output")
 (defvar |$texFormat| nil "if true produce tex output")
+(defvar |$mathmlFormat| nil "if true produce mathml output")
+(defvar |$htmlFormat| nil "if true produce html output")
+(defvar |$texFormat| nil "if true produce tex output")
 (defvar |$fortranFormat| nil "if true produce fortran output")
 (defvar |$algebraFormat| t "produce 2-d algebra output")
 (defvar |$kernelWarn| NIL "")
