added generation of HTML files to thy_read.ML;
authorclasohm
Tue, 24 Oct 1995 13:53:09 +0100
changeset 1291 e173be970d27
parent 1290 ee8f41456d28
child 1292 f55472745044
added generation of HTML files to thy_read.ML; removed old HTML package
src/Pure/Thy/ROOT.ML
src/Pure/Thy/blue_arrow.gif
src/Pure/Thy/chart.ML
src/Pure/Thy/red_arrow.gif
src/Pure/Thy/thy_read.ML
src/Pure/Thy/to_html.ML
--- a/src/Pure/Thy/ROOT.ML	Tue Oct 24 13:41:06 1995 +0100
+++ b/src/Pure/Thy/ROOT.ML	Tue Oct 24 13:53:09 1995 +0100
@@ -23,8 +23,8 @@
 
 structure ThySyn = ThySynFun(val user_keywords = [] and user_sections = []);
 structure ThmDB = ThmDBFun();
-structure Readthy = ReadthyFun(structure ThySyn = ThySyn and ThmDB = ThmDB);
-open ThmDB Readthy;
+structure ReadThy = ReadthyFun(structure ThySyn = ThySyn and ThmDB = ThmDB);
+open ThmDB ReadThy;
 
 (* hide functors; saves space in PolyML *)
 functor ThyScanFun() = struct end;
@@ -34,8 +34,11 @@
 fun init_thy_reader () =
   use_string
    ["structure ThmDB = ThmDBFun();",
-    "structure Readthy = ReadthyFun(structure ThySyn = ThySyn \
+    "structure ReadThy = ReadthyFun(structure ThySyn = ThySyn \
                                    \and ThmDB = ThmDB);",
-    "Readthy.loaded_thys := !loaded_thys;",
+    "ReadThy.loaded_thys := !loaded_thys;",
+    "ReadThy.gif_path := !gif_path;",
+    "ReadThy.chart00_path := !chart00_path;",
+    "ReadThy.make_html := !make_html;",
     "ThmDB.thm_db := !thm_db;",
-    "open ThmDB Readthy;"];
+    "open ThmDB ReadThy;"];
Binary file src/Pure/Thy/blue_arrow.gif has changed
--- a/src/Pure/Thy/chart.ML	Tue Oct 24 13:41:06 1995 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,377 +0,0 @@
-(*  ID:         $Id$
-    Author:	Mateja Jamnik, University of Cambridge
-    Copyright   1995  University of Cambridge
-
-   Generator of the dependency charts of Isabelle theories.
-*)
-
-
-(* --------------------
-   Declaration of the variables carrying the name 
-   of the location of source files:
-   
-   path -    location where the generated HTML files
-	     should be stored
-   srcpath - location where the source files are stored
-	     (ie. the graphics files)
-   -------------------- *)
-
-val htmlpath = "/homes/lcp/html_isa/";
-val srcpath = "/homes/lcp/Isa/Theory/";
-
-
-
-(* --------------------
-   Notices that display the legend for every dependency 
-   chart, and the link back to the main listing of all
-   theories.
-   -------------------- *)
-
-val notice1 =
-"<BR>\n"^"The name of the file is linked to the theory file <BR>\n";
-
-val notice2 =
-"<IMG SRC = \""^srcpath^"red_arrow.gif\" ALT = (sub)></A>\n"^
-" stands for subtheories (child theories) <BR>\n"^
-
-"<IMG SRC = \""^srcpath^"blue_arrow.gif\" ALT = (super)></A>\n"^
-" stands for supertheories (parent theories) <BR>\n<BR>\n";
-
-
-val back = "<A HREF = \""^htmlpath^"00-chart.html\">Back</A>\n"^
-" to the original listing of all the theories. <BR>\n<HR>\n<BR>\n";
-
-
-
-(* --------------------
-   Get a list of all theory files in Isabelle
-   that have been loaded.
-   -------------------- *)
-
-print_depth 1000;
-
-val theory_list = !loaded_thys;
-
-val files = Symtab.alist_of (theory_list);
-
-
-
-(* --------------------
-   Get a list of all theory files and their children.
-   -------------------- *)
-
-fun subtheory (tname, ThyInfo{children,...}) = (tname,children);
-
-val subtheories = map subtheory (files);
-
-
-
-(* --------------------
-   Extract a list of all theory files only.
-   -------------------- *)
-
-fun theory ( [], list ) = list
-  | theory ( (string, _)::rest, list ) = theory(rest, string::list);
-
-
-
-(* --------------------
-   Use quick sort to sort the theories in
-   the alphabetic order. Variable a as the first 
-   element of the list is used as a pivot value.
-   -------------------- *)
-
-fun quick [] = []
-  | quick [x] = [x]
-  | quick (a::bs) = let
-          fun part (l,r,[]) : string list = (quick l) @ (a::quick r)
-            | part (l,r,x::xs) = if x<=a then part(x::l, r, xs)
-                                         else part(l, x::r, xs)
-          in part([], [], bs) end;
-
-val theories = quick(theory(subtheories,[]));
-
-
-
-(* --------------------
-   Insert the identifier of the supertheory
-   matrix for every row. Also insert elements
-   into the list of identifier's parents in
-   alphabetic order.
-   -------------------- *)
-
-fun listins ( l, [], x:string ) = l@[x]
-  | listins ( l, e::r, x ) = if x>e then listins( l@[e], r, x )
-                                    else if x<>e then l@[x,e]@r
-					         else l@[x]@r;
-
-
-
-(* --------------------
-   Arguments:
-   t         - accumulator of the resulting supertheory matrix
-   result    - temporary resulting matrix (up until now)
-   (e,ident) - a list of identifier and its child
-   The child e of subtheory matrix becomes identifier ident of
-   the supertheory matrix. The identifier ident of subtheory
-   matrix becomes the parent elem of supertheory matrix.
-   Call function:
-		- listins
-   -------------------- *)
-
-fun matins ( t, [], (ident:string, elem:string) ) = t@[(ident,[elem])]
-  | matins ( t, (x:string,y:string list)::b, 
-	        (ident:string, elem:string) ) =
-    if x=ident then t@[(x,listins([],y,elem))]@b
-               else matins (t@[(x,y)], b, (ident,elem));
-
-
-
-(* --------------------
-   Instantiate the identifier ident, and the list of
-   its children (e::l), where e is its first child.
-   Call function:
-		- matins
-   -------------------- *)
-
-fun rowins ( (ident, []), result ) = result
-  | rowins ( (ident, e::l), result ) =
-    rowins ( (ident, l), matins([],result,(e,ident)) );
-
-
-
-(* --------------------
-   Extract recursively one row at a time of the
-   subtheory matrix.
-   Call function:
-		-rowins
-   -------------------- *)
-
-fun matinv ( [], result ) = result
-  | matinv ( l::b, result ) = matinv( b, rowins(l, result) );
-
-
-
-(* --------------------
-   Holds the value of supertheory matrix.
-   Call function:
-		-matinv
-   -------------------- *)
-
-val supertheories = matinv ( subtheories, [] );
-
-
-
-
-(* ---------------------------------------------------------------------- *)
-
-
-
-
-(* --------------------
-   Entries for the main chart of all the theories.
-   Every theory name is a link to the theory definition.
-   Down arrow is a link to the subtheory chart of that theory.
-   Up arrow is a link to the supertheory chart of that theory.
-   -------------------- *)
-
-fun entries x = "\n"^
-    "<A HREF = \""^htmlpath^x^
-    "_sub.html\">\n<IMG SRC = \""^srcpath^
-    "red_arrow.gif\" ALT = (sub)></A>\n"^
-
-    "<A HREF = \""^htmlpath^x^
-    "_sup.html\">\n<IMG SRC = \""^srcpath^
-    "blue_arrow.gif\" ALT = (super)></A> \n"^
-    "<A HREF = \""^htmlpath^x^".html\">"^x^"</A><BR>\n";
-
-fun all_list x = map entries x;
-
-
-
-(* --------------------
-   Convert a list of characters and strings
-   into a string.
-   -------------------- *)
-
-fun join ([],res) = res
-  | join (x::xs,res) = join(xs,res^x);
-
-
-
-val bottom =
-"<HR>\n\n"^
-"<! ---------------------------------------------------------------- >\n\n";
-
-
-
-(* --------------------
-   Find the row of the matrix into which
-   the parent (or children) theories
-   are going to be inserted.
-   -------------------- *)
-
-fun findline (_,[]) = []
-  | findline (th:string,(id,row:string list)::mat) =
-    if th=id then row else findline(th,mat);
-
-
-
-(* --------------------
-   Once a parent (or child) theory has been identified
-   make an entry for it with appropriate indentation and with
-   further links to its parent (or child) dependency chart.
-   It contains the subfunction:
-           - maketableentry
-   -------------------- *)
-
-fun dependencies (th, mat) =
-    let
-	val stringlist = findline(th,mat);
-	fun maketableentry name =
-	    "<LI> <A HREF=\""^htmlpath^name^".html\">"^name^"</A>\n"^
-	    " <A HREF = \""^htmlpath^name^
-	    "_sub.html\">\n<IMG SRC = \""^srcpath^
-	    "red_arrow.gif\" ALT = (sub)></A> \n"^
-	    "<A HREF = \""^htmlpath^name^
-	    "_sup.html\">\n<IMG SRC = \""^srcpath^
-	    "blue_arrow.gif\" ALT = (super)></A>\n"^
-	    "<UL>\n"^
-	    join(dependencies(name,mat),"")^
-	    "</UL>\n"
-    in
-	map maketableentry stringlist
-    end;
-
-
-
-(* --------------------
-   Create individual super- and sub-theory charts for
-   each theory. Store them in separate files.
-   It contains the subfunction:
-             - page
-   -------------------- *)
-
-fun pages ([],_,_,_) = 0
-  | pages (th::theories,theorymatrix,suffix,headline) =
-    let
-	fun page th =
-	    let
-
-		(* Open files for output of individual charts. *)
-
-		val outf_each = open_out (htmlpath^th^"_"^suffix^".html")
-	    in
-
-		(* Recursively write to the output files the *)
-                (* dependent theories with appropriate links *)
-		(* depending upon the suffix.		     *)
-
-		output(outf_each,
-
-			(* Heading of each dependency chart. *)
-
-		       "<A NAME=\""^th^"_"^suffix^".html\"></a>\n"^
-		       "<BR><H1>"^headline^"</H1>\n\n"^notice1^notice2^back^
-		       "\n"^"<A HREF=\""^htmlpath^th^".html\">"^th^"</A>\n"^
-		       (if suffix="sup"
-			    then ("<A HREF = \""^htmlpath^th^
-				 "_sub.html\">\n<IMG SRC = \""^srcpath^
-				 "red_arrow.gif\" ALT = (sub)></A>\n")
-			    else ("<A HREF = \""^htmlpath^th^
-				 "_sup.html\">\n<IMG SRC = \""^srcpath^
-				 "blue_arrow.gif\" ALT = (super)></A>\n"))^
-				 "<UL>\n");
-
-		(* Recursively call the function dependencies  *)
-		(* to create an entry in the chart for all the *)
-		(* levels of dependencies in the hierarchical  *)
-		(* structure of theory files for a given       *)
-		(* theory.                                     *)
-
-		output(outf_each,
-		       join(dependencies(th,theorymatrix),""));
-
-		output(outf_each,
-		       "</UL>\n"^bottom);
-
-		(* Close for output the individual *)
-	        (* dependency charts.              *)
-
-		close_out (outf_each)
-	    end;
-    in
-
-	(* Anti-bugging technique to follow the *) 
-	(* execution of the program.	       *)
-
-	output(std_out,"theory: "^th^"\n");
-
-
-	(* The main driver for the creation of the dependencies *)
-	(* which calls the functions page and pages. This will  *)
-	(* go into depth of dependency of each theory with the  *)
-	(* appropriate indentation.				*)
-
-	page(th);
-	pages(theories,theorymatrix,suffix,headline)
-    end;
-
-
-
-
-(* ---------------------------------------------------------------------- *)
-
-
-
-
-(* --------------------
-   Generate the main chart 00-chart.html containing 
-   the listing of all the theories and the links to charts.
-   -------------------- *)
-
-val outtext = htmlpath^"00-chart.html";
-val outfile = open_out outtext;
-
-val head = "<HTML>\n<HEAD>\n<TITLE>"^outtext^
-    "</TITLE>\n</HEAD>\n\n"^"<BODY>\n";
-
-val title = "<H1>Dependency Diagram</H1></P>\n\n"^notice1^notice2;
-val page1part1 = "<H2>Subtheories and Supertheories</H2>\n<BR>\n\n"^
-    join(all_list(theories),"")^"<BR>\n";
-val page1part3 = bottom;
-
-val tail = "</BODY>\n"^"</HTML>";
-
-output(outfile,head);
-output(outfile,title);
-output(outfile,page1part1);
-output(outfile,page1part3);
-
-
-
-(* ---------------------------------------------------------------------- *)
-
-
-
-(* --------------------
-   The main driver to create individual super- and sub-theory
-   charts for each individual theory. The arguments passed are:
-          - the list of all the theories
-          - the super- or sub-theory matrix
-	  - the appropriate suffix sup or sub
-	  - the title of the chart
-   It calls the function:
-          - pages
-   -------------------- *)
-
-pages(theories,subtheories,"sub","Subtheories");
-pages(theories,supertheories,"sup","Supertheories");
-output(outfile,tail);
-
-
-
-(* --------------------
-   Close file for output.
-   -------------------- *)
-close_out(outfile);
Binary file src/Pure/Thy/red_arrow.gif has changed
--- a/src/Pure/Thy/thy_read.ML	Tue Oct 24 13:41:06 1995 +0100
+++ b/src/Pure/Thy/thy_read.ML	Tue Oct 24 13:53:09 1995 +0100
@@ -9,14 +9,13 @@
 *)
 
 (*Type for theory storage*)
-datatype thy_info = ThyInfo of {path: string,
-                                children: string list,
-                                thy_time: string option,
-                                ml_time: string option,
-                                theory: theory option,
-                                thms: thm Symtab.table,
-                                thy_ss: Simplifier.simpset option,
-                                simpset: Simplifier.simpset option};
+datatype thy_info =
+  ThyInfo of {path: string,
+              children: string list, parents: string list,
+              thy_time: string option, ml_time: string option,
+              theory: theory option, thms: thm Symtab.table,
+              thy_ss: Simplifier.simpset option,
+              simpset: Simplifier.simpset option};
       (*meaning of special values:
         thy_time, ml_time = None     theory file has not been read yet
                           = Some ""  theory was read but has either been marked
@@ -24,6 +23,15 @@
                                      this theory (see e.g. 'virtual' theories
                                      like Pure or theories without a ML file)
         theory = None  theory has not been read yet
+
+        parents: While 'children' contains all theories the theory depends
+                 on (i.e. also ones quoted in the .thy file),
+                 'parents' only contains the theories which were used to form
+                 the base of this theory.
+
+        origin of the simpsets:
+        thy_ss: snapshot of !Simpset.simpset after .thy file was read
+        simpset: snapshot of !Simpset.simpset after .ML file was read
        *)
 
 signature READTHY =
@@ -44,6 +52,9 @@
 
   val theory_of_sign: Sign.sg -> theory
   val theory_of_thm: thm -> theory
+  val children_of: string -> string list
+  val parents_of: string -> string list
+
   val store_thm: string * thm -> thm
   val bind_thm: string * thm -> unit
   val qed: string -> unit
@@ -55,6 +66,12 @@
   val thms_of: theory -> (string * thm) list
   val simpset_of: string -> Simplifier.simpset
   val print_theory: theory -> unit
+
+  val gif_path       : string ref
+  val chart00_path   : string ref
+  val make_html      : bool ref
+  val init_html: unit -> unit
+  val make_chart: unit -> unit
 end;
 
 
@@ -66,29 +83,52 @@
 datatype basetype = Thy  of string
                   | File of string;
 
-val loaded_thys = ref (Symtab.make [("ProtoPure",
-                                     ThyInfo {path = "",
-                                       children = ["Pure", "CPure"],
-                                       thy_time = Some "", ml_time = Some "",
-                                       theory = Some proto_pure_thy,
-                                       thms = Symtab.null,
-                                       thy_ss = None, simpset = None}),
-                                    ("Pure", ThyInfo {path = "", children = [],
-                                       thy_time = Some "", ml_time = Some "",
-                                       theory = Some pure_thy,
-                                       thms = Symtab.null,
-                                       thy_ss = None, simpset = None}),
-                                    ("CPure", ThyInfo {path = "",
-                                       children = [],
-                                       thy_time = Some "", ml_time = Some "",
-                                       theory = Some cpure_thy,
-                                       thms = Symtab.null,
-                                       thy_ss = None, simpset = None})
-                                   ]);
+val loaded_thys =
+  ref (Symtab.make [("ProtoPure",
+                     ThyInfo {path = "",
+                              children = ["Pure", "CPure"], parents = [],
+                              thy_time = Some "", ml_time = Some "",
+                              theory = Some proto_pure_thy, thms = Symtab.null,
+                              thy_ss = None, simpset = None}),
+                    ("Pure",
+                     ThyInfo {path = "", children = [],
+                              parents = ["ProtoPure"],
+                              thy_time = Some "", ml_time = Some "",
+                              theory = Some pure_thy, thms = Symtab.null,
+                              thy_ss = None, simpset = None}),
+                    ("CPure",
+                     ThyInfo {path = "",
+                              children = [], parents = ["ProtoPure"],
+                              thy_time = Some "", ml_time = Some "",
+                              theory = Some cpure_thy,
+                              thms = Symtab.null,
+                              thy_ss = None, simpset = None})
+                   ]);
 
-val loadpath = ref ["."];           (*default search path for theory files *)
+val loadpath = ref ["."];              (*default search path for theory files*)
+
+val delete_tmpfiles = ref true;            (*remove temporary files after use*)
+
 
-val delete_tmpfiles = ref true;         (*remove temporary files after use *)
+(*Set location of graphics for HTML files
+  (When this is executed for the first time we are in $ISABELLE/Pure/Thy.
+   This path is converted to $ISABELLE/Tools by removing the last two
+   directories and appending "Tools". All subsequently made ReadThy
+   structures inherit this value.)
+*)
+val gif_path = ref (tack_on ("/" ^
+  space_implode "/" (rev (tl (tl (rev (space_explode "/" (pwd ())))))))
+  "Tools");
+
+(*Location of theory-list.txt and 00-chart.html (normally set by init_html)*)
+val chart00_path = ref "";     
+
+val make_html = ref false;      (*don't make HTML versions of loaded theories*)
+
+(*HTML file of theory currently being read
+  (Initialized by thyfile2html; used by use_thy and store_thm)*)
+val cur_htmlfile = ref None : outstream option ref;
+                                   
 
 (*Make name of the output ML file for a theory *)
 fun out_name tname = "." ^ tname ^ ".thy.ML";
@@ -136,38 +176,42 @@
        end
     | None => (false, false)
 
+(*Get all direct descendants of a theory*)
+fun children_of t =
+  case get_thyinfo t of Some (ThyInfo {children, ...}) => children
+                      | _ => [];
+
 (*Get all direct ancestors of a theory*)
-fun get_parents child =
-  let fun has_child (tname, ThyInfo {children, theory, ...}) = 
-        if child mem children then Some tname else None;
-  in mapfilter has_child (Symtab.dest (!loaded_thys)) end;
+fun parents_of t =
+  case get_thyinfo t of Some (ThyInfo {parents, ...}) => parents
+                      | _ => [];
 
 (*Get all descendants of a theory list *)
 fun get_descendants [] = []
   | get_descendants (t :: ts) =
-      let val tinfo = get_thyinfo t
-      in if is_some tinfo then
-           let val ThyInfo {children, ...} = the tinfo
-           in children union (get_descendants (children union ts))
-           end
-         else []
-      end;
+      let val children = children_of t
+      in children union (get_descendants (children union ts)) end;
 
 (*Get theory object for a loaded theory *)
-fun get_theory name =
+fun theory_of name =
   let val ThyInfo {theory, ...} = the (get_thyinfo name)
   in the theory end;
 
+(*Get path where theory's files are located*)
+fun path_of tname =
+  let val ThyInfo {path, ...} = the (get_thyinfo tname)
+  in path end;
+
 exception FILE_NOT_FOUND;   (*raised by find_file *)
 
 (*Find a file using a list of paths if no absolute or relative path is
   specified.*)
 fun find_file "" name =
-      let fun find_it (curr :: paths) =
-                if file_exists (tack_on curr name) then
-                    tack_on curr name
+      let fun find_it (cur :: paths) =
+                if file_exists (tack_on cur name) then
+                  (if cur = "." then name else tack_on cur name)
                 else
-                    find_it paths
+                  find_it paths
            | find_it [] = ""
       in find_it (!loadpath) end
   | find_file path name =
@@ -219,9 +263,9 @@
 
 (*Remove theory from all child lists in loaded_thys *)
 fun unlink_thy tname =
-  let fun remove (ThyInfo {path, children, thy_time, ml_time, theory, thms,
-                           thy_ss, simpset}) =
-        ThyInfo {path = path, children = children \ tname,
+  let fun remove (ThyInfo {path, children, parents, thy_time, ml_time,
+                           theory, thms, thy_ss, simpset}) =
+        ThyInfo {path = path, children = children \ tname, parents = parents,
                  thy_time = thy_time, ml_time = ml_time, theory = theory, 
                  thms = thms, thy_ss = thy_ss, simpset = simpset}
   in loaded_thys := Symtab.map remove (!loaded_thys) end;
@@ -234,15 +278,13 @@
 (*Change thy_time and ml_time for an existent item *)
 fun set_info tname thy_time ml_time =
   let val tinfo = case Symtab.lookup (!loaded_thys, tname) of
-          Some (ThyInfo {path, children, theory, thms, thy_ss, simpset,...}) =>
-            ThyInfo {path = path, children = children,
+          Some (ThyInfo {path, children, parents, theory, thms,
+                         thy_ss, simpset,...}) =>
+            ThyInfo {path = path, children = children, parents = parents,
                      thy_time = thy_time, ml_time = ml_time,
                      theory = theory, thms = thms,
                      thy_ss = thy_ss, simpset = simpset}
-        | None => ThyInfo {path = "", children = [],
-                           thy_time = thy_time, ml_time = ml_time,
-                           theory = None, thms = Symtab.null,
-                           thy_ss = None, simpset = None};
+        | None => error ("set_info: theory " ^ tname ^ " not found");
   in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys)
   end;
 
@@ -250,14 +292,205 @@
 fun mark_outdated tname =
   let val t = get_thyinfo tname;
   in if is_none t then ()
-     else let val ThyInfo {thy_time, ml_time, ...} = the t
-          in set_info tname
-                      (if is_none thy_time then None else Some "")
-                      (if is_none ml_time then None else Some "")
-                      
-          end
+     else
+       let val ThyInfo {thy_time, ml_time, ...} = the t
+       in set_info tname (if is_none thy_time then None else Some "")
+                         (if is_none ml_time then None else Some "")
+       end
   end;
 
+(*Make head of HTML dependency charts
+  Parameters are:
+    file: HTML file
+    tname: theory name
+    suffix: suffix of complementary chart
+            (sup if this head is for a sub-chart, sub if it is for a sup-chart;
+             empty for Pure and CPure sub-charts)
+    gif_path: relative path to directory containing GIFs
+    chart00_path: relative path to directory containing main theory chart
+*)
+fun mk_charthead file tname title green_arrow gif_path chart00_path package =
+  output (file,
+   "<HTML><HEAD><TITLE>" ^ title ^ " of " ^ tname ^
+   "</TITLE></HEAD>\n<H2>" ^ title ^ " of theory " ^ tname ^
+   "</H2>\nThe name of every theory is linked to its theory file<BR>\n" ^
+   "<IMG SRC = \"" ^ tack_on gif_path "red_arrow.gif\
+   \\" ALT = \\/></A> stands for subtheories (child theories)<BR>\n\
+   \<IMG SRC = \"" ^ tack_on gif_path "blue_arrow.gif\
+   \\" ALT = /\\></A> stands for supertheories (parent theories)\n" ^
+   (if not green_arrow then "" else
+      "<BR><IMG SRC = \"" ^ tack_on gif_path "green_arrow.gif\
+      \\" ALT = &gt;></A> stands for repeated subtrees") ^
+   "<P><A HREF = \"" ^ tack_on chart00_path "00-chart.html\
+   \\">Back</A> to the main theory chart of " ^ package ^ ".\n<HR>\n<PRE>");
+
+(*Convert .thy file to HTML and make chart of its super-theories*)
+fun thyfile2html tpath tname =
+  let
+    val gif_path = relative_path tpath (!gif_path);
+    val package = hd (rev (space_explode "/" (!chart00_path)));
+    val chart00_path = relative_path tpath (!chart00_path);
+
+    (*Make list of all theories and all theories that own a .thy file*)
+    fun list_theories [] theories thy_files = (theories, thy_files)
+      | list_theories ((tname, ThyInfo {thy_time, ...}) :: ts)
+                      theories thy_files =
+          list_theories ts (tname :: theories)
+            (if is_some thy_time andalso the thy_time <> "" then
+               tname :: thy_files
+             else thy_files);
+
+    val (theories, thy_files) =
+      list_theories (Symtab.dest (!loaded_thys)) [] [];
+
+    (*Do the conversion*)
+    fun gettext thy_file  =
+      let
+        (*Convert special HTML characters ('&', '>', and '<')*)
+        val file =
+          explode (execute ("sed -e 's/\\&/\\&amp;/g' -e 's/>/\\&gt;/g' \
+                            \-e 's/</\\&lt;/g' " ^ thy_file));
+
+        (*Isolate first (possibly nested) comment;
+          skip all leading whitespaces*)
+        val (comment, file') =
+          let fun first_comment ("*" :: ")" :: cs) co 1 = (co ^ "*)", cs)
+                | first_comment ("*" :: ")" :: cs) co d =
+                    first_comment cs (co ^ "*)") (d-1)
+                | first_comment ("(" :: "*" :: cs) co d =
+                    first_comment cs (co ^ "(*") (d+1)
+                | first_comment (" "  :: cs) "" 0 = first_comment cs "" 0
+                | first_comment ("\n" :: cs) "" 0 = first_comment cs "" 0
+                | first_comment ("\t" :: cs) "" 0 = first_comment cs "" 0
+                | first_comment cs           "" 0 = ("", cs)
+                | first_comment (c :: cs) co d =
+                    first_comment cs (co ^ implode [c]) d
+                | first_comment [] co _ =
+                    error ("Unexpected end of file " ^ tname ^ ".thy.");
+          in first_comment file "" 0 end;
+
+        (*Process line defining theory's ancestors;
+          convert valid theory names to links to their HTML file*)
+        val (ancestors, body) =
+          let
+            fun make_links l result =
+              let val (pre, letter) = take_prefix (not o is_letter) l;
+
+                  val (id, rest) =
+                    take_prefix (is_quasi_letter orf is_digit) letter;
+
+                  val id = implode id;
+
+                  (*Make a HTML link out of a theory name*)
+                  fun make_link t =
+                    let val path = path_of t;
+                    in "<A HREF = \"" ^
+                       tack_on (relative_path tpath path) t ^
+                       ".html\">" ^ t ^ "</A>" end;
+              in if not (id mem theories) then (result, implode l)
+                 else if id mem thy_files then
+                   make_links rest (result ^ implode pre ^ make_link id)
+                 else make_links rest (result ^ implode pre ^ id)
+              end;
+
+            val (pre, rest) = take_prefix (fn c => c <> "=") file';
+
+            val (ancestors, body) =
+              if null rest then
+                error ("Missing \"=\" in file " ^ tname ^ ".thy.\n\
+                       \(Make sure that the last line ends with a linebreak.)")
+              else
+                make_links rest "";
+          in (implode pre ^ ancestors, body) end;
+      in "<HTML><HEAD><TITLE>" ^ tname ^ ".thy</TITLE></HEAD>\n\n<BODY>\n" ^
+         "<H2>" ^ tname ^ ".thy</H2>\n<A HREF = \"" ^
+         tack_on chart00_path "00-chart.html\
+         \\">Back</A> to the main theory chart of " ^ package ^
+         ".\n<HR>\n\n<PRE>\n" ^ comment ^ ancestors ^ body ^
+         "</PRE>\n<HR><H2>Theorems proved in <A HREF = \"" ^ tname ^
+         ".ML\">" ^ tname ^ ".ML</A>:</H2>\n"
+      end;
+
+    (** Make chart of super-theories **)
+
+    val sup_out = open_out (tack_on tpath tname ^ "_sup.html");
+    val sub_out = open_out (tack_on tpath tname ^ "_sub.html");
+
+    (*Theories that already have been listed in this chart*)
+    val listed = ref [];
+
+    val wanted_theories =
+      filter (fn s => s mem thy_files orelse s = "Pure" orelse s = "CPure")
+             theories;
+
+    (*Make nested list of theories*)
+    fun list_ancestors tname level continued =
+      let
+        fun mk_entry [] = ()
+          | mk_entry (t::ts) =
+            let
+              val is_pure = t = "Pure" orelse t = "CPure";
+              val path = path_of t;
+              val rel_path = if is_pure then chart00_path
+                             else relative_path tpath path;
+
+              fun mk_offset [] cur =
+                    if level < cur then error "Error in mk_offset"
+                    else implode (replicate (level - cur) "    ")
+                | mk_offset (l::ls) cur =
+                    implode (replicate (l - cur) "    ") ^ "|   " ^
+                    mk_offset ls (l+1);
+            in output (sup_out,
+                 " " ^ mk_offset continued 0 ^
+                 "\\__" ^ (if is_pure then t else "<A HREF=\"" ^ 
+                             tack_on rel_path t ^ ".html\">" ^ t ^ "</A>") ^
+                 " <A HREF = \"" ^ tack_on rel_path t ^
+                 "_sub.html\"><IMG ALIGN=TOP SRC = \"" ^
+                 tack_on gif_path "red_arrow.gif\" ALT = \\/></A>" ^
+                 (if is_pure then ""
+                  else "<A HREF = \"" ^ tack_on rel_path t ^
+                       "_sup.html\"><IMG ALIGN=TOP SRC = \"" ^
+                       tack_on gif_path "blue_arrow.gif\
+                       \\" ALT = /\\></A>"));
+              if t mem (!listed) andalso not (null (parents_of t)) then
+                output (sup_out,
+                  "<A HREF = \"" ^ tack_on rel_path t ^ "_sup.html\">\
+                  \<IMG ALIGN=TOP SRC = \"" ^
+                  tack_on gif_path "green_arrow.gif\" ALT = &gt;></A>\n")
+              else (output (sup_out, "\n");
+                    listed := t :: (!listed);
+                    list_ancestors t (level+1) (if null ts then continued
+                                                else continued @ [level]);
+                    mk_entry ts)
+            end;
+
+        val relatives =
+          filter (fn s => s mem wanted_theories) (parents_of tname);
+      in mk_entry relatives end;
+  in if is_some (!cur_htmlfile) then
+       error "thyfile2html: Last theory's HTML has not been closed."
+     else ();
+     cur_htmlfile := Some (open_out (tack_on tpath tname ^ ".html"));
+     output (the (!cur_htmlfile), gettext (tack_on tpath tname ^ ".thy"));
+
+     mk_charthead sup_out tname "Ancestors" true gif_path chart00_path package;
+     output(sup_out,
+       "<A HREF=\"" ^ tname ^ ".html\">" ^ tname ^ "</A> \
+       \<A HREF = \"" ^ tname ^ "_sub.html\"><IMG ALIGN=TOP SRC = \"" ^
+       tack_on gif_path "red_arrow.gif\" ALT = \\/></A>\n");
+     list_ancestors tname 0 [];
+     output (sup_out, "</PRE><HR></BODY></HTML>");
+     close_out sup_out;
+
+     mk_charthead sub_out tname "Children" false gif_path chart00_path package;
+     output(sub_out,
+       "<A HREF=\"" ^ tname ^ ".html\">" ^ tname ^ "</A> \
+       \<A HREF = \"" ^ tname ^ "_sup.html\"><IMG SRC = \"" ^
+       tack_on gif_path "blue_arrow.gif\" ALT = \\/></A>\n");
+     close_out sub_out
+  end;
+
+
 (*Read .thy and .ML files that haven't been read yet or have changed since
   they were last read;
   loaded_thys is a thy_info list ref containing all theories that have
@@ -270,14 +503,16 @@
     val (abs_path, _) = if thy_file = "" then split_filename ml_file
                         else split_filename thy_file;
     val (thy_uptodate, ml_uptodate) = thy_unchanged tname thy_file ml_file;
+    val old_parents = parents_of tname;
 
     (*Set absolute path for loaded theory *)
     fun set_path () =
-      let val ThyInfo {children, thy_time, ml_time, theory, thms, thy_ss,
-                       simpset, ...} =
+      let val ThyInfo {children, parents, thy_time, ml_time, theory, thms,
+                       thy_ss, simpset, ...} =
             the (Symtab.lookup (!loaded_thys, tname));
       in loaded_thys := Symtab.update ((tname,
-                          ThyInfo {path = abs_path, children = children,
+                          ThyInfo {path = abs_path,
+                                   children = children, parents = parents,
                                    thy_time = thy_time, ml_time = ml_time,
                                    theory = theory, thms = thms,
                                    thy_ss = thy_ss, simpset = simpset}),
@@ -286,7 +521,7 @@
 
     (*Mark all direct descendants of a theory as changed *)
     fun mark_children thy =
-      let val ThyInfo {children, ...} = the (get_thyinfo thy);
+      let val children = children_of thy;
           val present = filter (is_some o get_thyinfo) children;
           val loaded = filter already_loaded present;
       in if loaded <> [] then
@@ -301,13 +536,13 @@
     fun delete_thms () =
       let
         val tinfo = case get_thyinfo tname of
-            Some (ThyInfo {path, children, thy_time, ml_time, theory, thy_ss,
-                           simpset, ...}) =>
-              ThyInfo {path = path, children = children,
+            Some (ThyInfo {path, children, parents, thy_time, ml_time, theory,
+                           thy_ss, simpset, ...}) =>
+              ThyInfo {path = path, children = children, parents = parents,
                        thy_time = thy_time, ml_time = ml_time,
                        theory = theory, thms = Symtab.null,
                        thy_ss = thy_ss, simpset = simpset}
-          | None => ThyInfo {path = "", children = [],
+          | None => ThyInfo {path = "", children = [], parents = [],
                              thy_time = None, ml_time = None,
                              theory = None, thms = Symtab.null,
                              thy_ss = None, simpset = None};
@@ -320,10 +555,11 @@
       end;
 
     fun save_thy_ss () =
-      let val ThyInfo {path, children, thy_time, ml_time, theory, thms,
-                       simpset, ...} = the (get_thyinfo tname);
+      let val ThyInfo {path, children, parents, thy_time, ml_time,
+                       theory, thms, simpset, ...} = the (get_thyinfo tname);
       in loaded_thys := Symtab.update
-           ((tname, ThyInfo {path = path, children = children,
+           ((tname, ThyInfo {path = path,
+                             children = children, parents = parents,
                              thy_time = thy_time, ml_time = ml_time,
                              theory = theory, thms = thms,
                              thy_ss = Some (!Simplifier.simpset),
@@ -332,10 +568,11 @@
       end;
 
     fun save_simpset () =
-      let val ThyInfo {path, children, thy_time, ml_time, theory, thms,
-                       thy_ss, ...} = the (get_thyinfo tname);
+      let val ThyInfo {path, children, parents, thy_time, ml_time,
+                       theory, thms, thy_ss, ...} = the (get_thyinfo tname);
       in loaded_thys := Symtab.update
-           ((tname, ThyInfo {path = path, children = children,
+           ((tname, ThyInfo {path = path,
+                             children = children, parents = parents,
                              thy_time = thy_time, ml_time = ml_time,
                              theory = theory, thms = thms,
                              thy_ss = thy_ss,
@@ -343,22 +580,58 @@
             !loaded_thys)
       end;
 
+   (*Add theory to file listing all loaded theories (for 00-chart.html)
+     and to the sub-charts of its parents*)
+   fun mk_html () =
+     let val new_parents = parents_of tname \\ old_parents;
+
+         (*Add child to parents' sub-theory charts*)
+         fun add_to_parents t =
+           let val is_pure = t = "Pure" orelse t = "CPure";
+               val path = if is_pure then (!chart00_path) else path_of t;
+
+               val gif_path = relative_path path (!gif_path);
+               val rel_path = relative_path path abs_path;
+
+               val out = open_append (tack_on path t ^ "_sub.html");
+           in output (out,
+                " |\n \\__<A HREF=\"" ^ tack_on rel_path tname ^ ".html\">" ^
+                tname ^ "</A> <A HREF = \"" ^
+                tack_on rel_path tname ^
+                "_sub.html\"><IMG ALIGN=TOP SRC = \"" ^
+                tack_on gif_path "red_arrow.gif\" ALT = \\/></A>\
+                \<A HREF = \"" ^ tack_on rel_path tname ^ "_sup.html\">\
+                \<IMG ALIGN=TOP SRC = \"" ^ tack_on gif_path "blue_arrow.gif\
+                \\" ALT = /\\></A>\n");
+              close_out out
+           end;
+
+         val theory_list =
+           open_append (tack_on (!chart00_path) "theory_list.txt");
+     in output (theory_list, tname ^ " " ^ abs_path ^ "\n");
+        close_out theory_list;
+
+        seq add_to_parents new_parents
+     end
   in if thy_uptodate andalso ml_uptodate then ()
      else
-     (
-       if thy_file = "" then ()
+      (if thy_file = "" then ()
        else if thy_uptodate then
          simpset := let val ThyInfo {thy_ss, ...} = the (get_thyinfo tname);
                     in the thy_ss end
        else
          (writeln ("Reading \"" ^ name ^ ".thy\"");
+
           delete_thms ();
           read_thy tname thy_file;
           use (out_name tname);
           save_thy_ss ();
 
           if not (!delete_tmpfiles) then ()
-          else delete_file (out_name tname)
+          else delete_file (out_name tname);
+
+          if not (!make_html) then ()
+          else thyfile2html abs_path tname
          );
 
        set_info tname (Some (file_info thy_file)) None;
@@ -375,21 +648,37 @@
 
        (*Store axioms of theory
          (but only if it's not a copy of an older theory)*)
-       let val parents = get_parents tname;
-           val fst_thy = get_theory (hd parents);
-           val this_thy = get_theory tname;
+       let val parents = parents_of tname;
+           val this_thy = theory_of tname;
            val axioms =
              if length parents = 1
-                andalso Sign.eq_sg (sign_of fst_thy, sign_of this_thy) then []
+                andalso Sign.eq_sg (sign_of (theory_of (hd parents)),
+                                    sign_of this_thy) then []
              else axioms_of this_thy;
        in map store_thm_db axioms end;
 
+       (*Add theory to list of all loaded theories (for 00-chart.html)
+         and add it to its parents' sub-charts*)
+       if !make_html then
+         let val path = path_of tname;
+         in if path = "" then mk_html ()    (*first time theory has been read*)
+            else ()
+         end
+       else ();
+
        (*Now set the correct info*)
        set_info tname (Some (file_info thy_file)) (Some (file_info ml_file));
        set_path ();
 
        (*Mark theories that have to be reloaded*)
-       mark_children tname
+       mark_children tname;
+
+       (*Close HTML file*)
+       case !cur_htmlfile of
+           Some out => (output (out, "<HR></BODY></HTML>\n");
+                        close_out out;
+                        cur_htmlfile := None)
+         | None => ()
       )
   end;
 
@@ -405,25 +694,19 @@
   let (*List theories in the order they have to be loaded *)
       fun load_order [] result = result
         | load_order thys result =
-            let fun next_level (t :: ts) =
-                      let val thy = get_thyinfo t
-                      in if is_some thy then
-                             let val ThyInfo {children, ...} = the thy
-                             in children union (next_level ts) end
-                         else next_level ts
-                      end
-                  | next_level [] = [];
+            let fun next_level [] = []
+                  | next_level (t :: ts) =
+                      let val children = children_of t
+                      in children union (next_level ts) end;
 
-                val children = next_level thys;
-            in load_order children ((result \\ children) @ children) end;
+                val descendants = next_level thys;
+            in load_order descendants ((result \\ descendants) @ descendants)
+            end;
 
       fun reload_changed (t :: ts) =
-            let val thy = get_thyinfo t;
-
-                fun abspath () =
-                  if is_some thy then
-                    let val ThyInfo {path, ...} = the thy in path end
-                  else "";
+            let fun abspath () = case get_thyinfo t of
+                                     Some (ThyInfo {path, ...}) => path
+                                   | None => "";
 
                 val (thy_file, ml_file) = get_filenames (abspath ()) t;
                 val (thy_uptodate, ml_uptodate) =
@@ -453,7 +736,7 @@
 (*Merge theories to build a base for a new theory.
   Base members are only loaded if they are missing.*)
 fun mk_base bases child mk_draft =
-  let (*Show the cycle that would be created by add_child *)
+  let (*Show the cycle that would be created by add_child*)
       fun show_cycle base =
         let fun find_it result curr =
               let val tinfo = get_thyinfo curr
@@ -468,22 +751,23 @@
               end
         in find_it "" child end;
 
-      (*Check if a cycle would be created by add_child *)
+      (*Check if a cycle would be created by add_child*)
       fun find_cycle base =
         if base mem (get_descendants [child]) then show_cycle base
         else ();
 
-      (*Add child to child list of base *)
+      (*Add child to child list of base*)
       fun add_child base =
         let val tinfo =
               case Symtab.lookup (!loaded_thys, base) of
-                  Some (ThyInfo {path, children, thy_time, ml_time,
+                  Some (ThyInfo {path, children, parents, thy_time, ml_time,
                            theory, thms, thy_ss, simpset}) =>
-                    ThyInfo {path = path, children = child ins children,
+                    ThyInfo {path = path,
+                             children = child ins children, parents = parents,
                              thy_time = thy_time, ml_time = ml_time,
                              theory = theory, thms = thms,
                              thy_ss = thy_ss, simpset = simpset}
-                | None => ThyInfo {path = "", children = [child],
+                | None => ThyInfo {path = "", children = [child], parents = [],
                                    thy_time = None, ml_time = None,
                                    theory = None, thms = Symtab.null,
                                    thy_ss = None, simpset = None};
@@ -516,7 +800,7 @@
       (*Load all needed files and make a list of all real theories *)
       fun load_base (Thy b :: bs) =
            (load b;
-            b :: (load_base bs))
+            b :: load_base bs)
         | load_base (File b :: bs) =
            (load b;
             load_base bs)                    (*don't add it to mergelist *)
@@ -525,26 +809,34 @@
       val dummy = unlink_thy child;
       val mergelist = load_base bases;
 
+      val dummy =
+        let val tinfo = case Symtab.lookup (!loaded_thys, child) of
+              Some (ThyInfo {path, children, thy_time, ml_time, theory, thms,
+                             thy_ss, simpset, ...}) =>
+                 ThyInfo {path = path,
+                          children = children, parents = mergelist,
+                          thy_time = thy_time, ml_time = ml_time,
+                          theory = theory, thms = thms,
+                          thy_ss = thy_ss, simpset = simpset}
+             | None => error ("set_parents: theory " ^ child ^ " not found");
+        in loaded_thys := Symtab.update ((child, tinfo), !loaded_thys) end;
+
       val base_thy = (writeln ("Loading theory " ^ (quote child));
-                      merge_thy_list mk_draft (map get_theory mergelist));
+                      merge_thy_list mk_draft (map theory_of mergelist));
  in simpset := foldr merge_ss (mapfilter get_simpset mergelist, empty_ss);
     base_thy
  end;
 
-(*Change theory object for an existent item of loaded_thys
-  or create a new item*)
+(*Change theory object for an existent item of loaded_thys*)
 fun store_theory (thy, tname) =
   let val tinfo = case Symtab.lookup (!loaded_thys, tname) of
-               Some (ThyInfo {path, children, thy_time, ml_time, thms,
+               Some (ThyInfo {path, children, parents, thy_time, ml_time, thms,
                               thy_ss, simpset, ...}) =>
-                 ThyInfo {path = path, children = children,
+                 ThyInfo {path = path, children = children, parents = parents,
                           thy_time = thy_time, ml_time = ml_time,
                           theory = Some thy, thms = thms,
                           thy_ss = thy_ss, simpset = simpset}
-             | None => ThyInfo {path = "", children = [],
-                                thy_time = None, ml_time = None,
-                                theory = Some thy, thms = Symtab.null,
-                                thy_ss = None, simpset = None};
+             | None => error ("store_theory: theory " ^ tname ^ " not found");
   in loaded_thys := Symtab.update ((tname, tinfo), !loaded_thys)
   end;
 
@@ -583,11 +875,12 @@
 
 (* Store theorems *)
 
-(*Store a theorem in the thy_info of its theory*)
+(*Store a theorem in the thy_info of its theory,
+  and in the theory's HTML file*)
 fun store_thm (name, thm) =
   let
-    val (thy_name, ThyInfo {path, children, thy_time, ml_time, theory, thms,
-                            thy_ss, simpset}) =
+    val (thy_name, ThyInfo {path, children, parents, thy_time, ml_time,
+                            theory, thms, thy_ss, simpset}) =
       thyinfo_of_sign (#sign (rep_thm thm));
 
     val (thms', duplicate) = (Symtab.update_new ((name, thm), thms), false)
@@ -598,13 +891,28 @@
             (thms, true))
          else error ("Duplicate theorem name " ^ quote s
                      ^ " used in theory database"));
+
+    fun thm_to_html () =
+      let fun escape []       = ""
+            | escape ("<"::s) = "&lt;" ^ escape s
+            | escape (">"::s) = "&gt;" ^ escape s
+            | escape ("&"::s) = "&amp;" ^ escape s
+            | escape (c::s)   = c ^ escape s;
+      in case !cur_htmlfile of
+             Some out =>
+               output (out, "<EM>" ^ name ^ "</EM>\n<PRE>" ^
+                            escape (explode (string_of_thm (freeze thm))) ^
+                            "</PRE><P>\n")
+           | None => ()
+      end;
   in
     loaded_thys := Symtab.update
-     ((thy_name, ThyInfo {path = path, children = children,
+     ((thy_name, ThyInfo {path = path, children = children, parents = parents,
                           thy_time = thy_time, ml_time = ml_time,
                           theory = theory, thms = thms',
                           thy_ss = thy_ss, simpset = simpset}),
       !loaded_thys);
+    thm_to_html ();
     if duplicate then thm else store_thm_db (name, thm)
   end;
 
@@ -613,19 +921,24 @@
 val qed_thm = ref flexpair_def(*dummy*);
 
 fun bind_thm (name, thm) =
-  (qed_thm := standard thm;
-   use_string ["val " ^name^ " = store_thm (" ^quote name^", !qed_thm);"]);
+ (qed_thm := standard thm;
+  store_thm (name, standard thm);
+  use_string ["val " ^ name ^ " = !qed_thm;"]);
 
 fun qed name =
-  use_string ["val " ^ name ^ " = store_thm (" ^ quote name ^ ", result ());"];
+ (qed_thm := result ();
+  store_thm (name, !qed_thm);
+  use_string ["val " ^ name ^ " = !qed_thm;"]);
 
 fun qed_goal name thy agoal tacsf =
-  (qed_thm := prove_goal thy agoal tacsf;
-   use_string ["val " ^ name ^ " = store_thm (" ^ quote name ^", !qed_thm);"]);
+ (qed_thm := prove_goal thy agoal tacsf;
+  store_thm (name, !qed_thm);
+  use_string ["val " ^ name ^ " = !qed_thm;"]);
 
 fun qed_goalw name thy rths agoal tacsf =
-  (qed_thm := prove_goalw thy rths agoal tacsf;
-   use_string ["val " ^ name ^ " = store_thm (" ^ quote name ^", !qed_thm);"]);
+ (qed_thm := prove_goalw thy rths agoal tacsf;
+  store_thm (name, !qed_thm);
+  use_string ["val " ^ name ^ " = !qed_thm;"]);
 
 
 (* Retrieve theorems *)
@@ -648,7 +961,7 @@
         | get (t::ts) ng searched =
             (case Symtab.lookup (thmtab_of_name t, name) of
                  Some thm => thm
-               | None => get ts (ng union (get_parents t)) (t::searched));
+               | None => get ts (ng union (parents_of t)) (t::searched));
 
       val (tname, _) = thyinfo_of_sign (sign_of thy);
   in get [tname] [] [] end;
@@ -677,4 +990,89 @@
 
 fun print_theory thy = (Drule.print_theory thy; print_thms thy);
 
+
+(* Misc HTML functions *)
+
+(*Init HTML generator by setting paths and creating new files*)
+fun init_html () =
+  let val pure_out = open_out "Pure_sub.html";
+      val cpure_out = open_out "CPure_sub.html";
+      val theory_list = close_out (open_out "theory_list.txt");
+
+      val rel_gif_path = relative_path (pwd ()) (!gif_path);
+      val package = hd (rev (space_explode "/" (pwd ())));
+  in make_html := true;
+     chart00_path := pwd();
+     writeln ("Setting path for 00-chart.html to " ^ quote (!chart00_path) ^
+              "\nGIF path has been set to " ^ quote (!gif_path));
+
+     mk_charthead pure_out "Pure" "Children" false rel_gif_path "" package;
+     mk_charthead cpure_out "CPure" "Children" false rel_gif_path "" package;
+     output (pure_out, "Pure\n");
+     output (cpure_out, "CPure\n");
+     close_out pure_out;
+     close_out cpure_out
+  end;
+
+(*Generate 00-chart.html*)
+fun make_chart () = if not (!make_html) then () else
+  let val theory_list = open_in (tack_on (!chart00_path) "theory_list.txt");
+      val theories = space_explode "\n" (input (theory_list, 999999));
+      val dummy = close_in theory_list;
+
+      (*Path to Isabelle's main directory = $gif_path/.. *)
+      val base_path = "/" ^
+        space_implode "/" (rev (tl (rev (space_explode "/" (!gif_path)))));
+
+      val gif_path = relative_path (!chart00_path) (!gif_path);
+
+      (*Make entry for main chart of all theories.*)
+      fun main_entries [] curdir =
+            implode (replicate (length curdir -1) "</UL>\n")
+        | main_entries (t::ts) curdir =
+            let
+              val (name, path) = take_prefix (not_equal " ") (explode t);
+
+              val tname = implode name
+              val tpath =
+                tack_on (relative_path (!chart00_path) (implode (tl path)))
+                        tname;
+              val subdir = space_explode "/"
+                                 (relative_path base_path (implode (tl path)));
+              val level_diff = length subdir - length curdir;
+            in "\n" ^
+               (if subdir <> curdir then
+                  (implode (if level_diff > 0 then
+                              replicate level_diff "<UL>\n"
+                            else if level_diff < 0 then
+                              replicate (~level_diff) "</UL>\n"
+                            else []) ^
+                  "<H3>" ^ space_implode "/" subdir ^ "</H3>\n")
+                else "") ^
+               "<A HREF = \"" ^ tpath ^ "_sub.html\"><IMG SRC = \"" ^
+               tack_on gif_path "red_arrow.gif\" ALT = \\/></A>" ^
+               "<A HREF = \"" ^ tpath ^ "_sup.html\"><IMG SRC = \"" ^
+               tack_on gif_path "blue_arrow.gif\
+               \\" ALT = /\\></A> <A HREF = \"" ^ tpath ^
+               ".html\">" ^ tname ^ "</A><BR>\n" ^
+               main_entries ts subdir
+            end;
+
+      val out = open_out (tack_on (!chart00_path) "00-chart.html");
+      val subdir = relative_path base_path (!chart00_path);
+  in output (out,
+       "<HTML><HEAD><TITLE>Isabelle/" ^ subdir ^ "</TITLE></HEAD>\n\
+       \<H2>Isabelle/" ^ subdir ^ "</H2>\n\
+       \The name of every theory is linked to its theory file<BR>\n\
+       \<IMG SRC = \"" ^ tack_on gif_path "red_arrow.gif\
+       \\" ALT = \\/></A> stands for subtheories (child theories)<BR>\n\
+       \<IMG SRC = \"" ^ tack_on gif_path "blue_arrow.gif\
+       \\" ALT = /\\></A> stands for supertheories (parent theories)\n\
+       \<P><A HREF = \"" ^
+       tack_on (relative_path (!chart00_path) base_path) "logics.html\">\
+       \Back</A> to the index of Isabelle logics.\n<HR>" ^
+       main_entries theories (space_explode "/" base_path) ^
+       "</BODY></HTML>\n");
+     close_out out
+  end;
 end;
--- a/src/Pure/Thy/to_html.ML	Tue Oct 24 13:41:06 1995 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,273 +0,0 @@
-(*  ID:         $Id$
-    Author:	Mateja Jamnik, University of Cambridge
-    Copyright   1995  University of Cambridge
-
-   Convert the Isabelle theory files to .html format for hypertext browsing
-*)
-
-val htmlpath = "/homes/lcp/html_isa/";
-
-(* --------------------
-   Exception declaration in case that there is a lexical
-   error occurs.
-   -------------------- *)
-
-exception lex_err;
-
-(* --------------------
-   Get the list of all the theory files and the
-   path to access them in their directories
-   -------------------- *)
-
-print_depth 1000;
-val theory_list = !loaded_thys;
-val files = Symtab.alist_of (theory_list);
-
-(* --------------------
-   The function move_eachf is going to move all the theory
-   files in isabelle to their html format. It takes 
-   for arguments the name of the theory (tname) and
-   other theory information such as path (path), theorems (thms)
-   proved, ... It is the main driver of the program, and basically
-   contains all other functions. It contains the following
-   subfunctions:
-     - create_pure
-     - gettext
-     - move_onef
-     - transform
-   -------------------- *)
-
-fun move_eachf (tname, ThyInfo{path,thms,...}) =
-    let val intext = path^tname^".thy";
-	val outtext = htmlpath^tname^".html";
-	    
-(* --------------------
-   The function gettext takes an instrem from the auxilliary 
-   file .thy whose name and path are specified in the existent
-   Isabelle structure, treats the inputted string with all the
-   necessary modifications for html format and puts it into the
-   file with the same name but .html extension. The subfunctions
-   it contains are:
-      - after_first_c
-      - filter
-      - first_comment
-      - format_link
-      - getstring
-      - get_word
-      - he
-      - html
-      - html_escape
-      - insert_link
-      - leading_comment
-      - lc_exists
-      - modify_body
-      - remove_lc
-      - rest
-      - thy_name
-   -------------------- *)
-
-	fun gettext is  =
-	    let 
-		val head = "<HTML>\n<HEAD>\n<TITLE>"^intext^
-		    "</TITLE>\n</HEAD>\n\n"^"<BODY>\n";
-		val title = "<H1>"^tname^".thy"^"</H1></P>\n\n"^
-		    "<BR>\n<A HREF = \""^htmlpath^
-		    "00-chart.html\">Dependency Chart</A>\n"^
-		    ": display of dependencies between the theories.\n"^
-		    "<BR>\n<HR>\n\n<PRE>\n";
-		val tail = "</PRE>"^"</BODY>\n"^"</HTML>";
-		
-
-	     (* --------------------
-		The function he (html escape) is going to take
-		every single characterof the input stream and check
-		for ">", "<" and "&" characters that have a special
-		meaning in html and convert them into their corresponding
-		escape sequences.   
-		-------------------- *)
-		fun he [] r = r
-		  | he ("<"::sl) r = he sl (r@["&","l","t"])
-		  | he (">"::sl) r = he sl (r@["&","g","t"])
-		  | he ("&"::sl) r = he sl (r@["&","a","m","p"])
-		  | he (c::sl) r = he sl (r@[c]);
-
-		fun html_escape sl = he sl [];
-
-	     (* --------------------
-		The function first_comment is a pattern checking for
-		nested comments. The argument d will keep track of how
-		deep we are in the nested comment. The function will
-		return the first comment extracted from the input stream,
-		so that we can copy it into the output stream. Lexical
-		error is raised if we open an empty file to read from.
-		-------------------- *)
-		fun first_comment ("*"::")"::cs) co 1 = co@["*",")"]
-		  | first_comment ("*"::")"::cs) co d =
-		    first_comment cs (co@["*",")"]) (d-1)
-		  | first_comment ("("::"*"::cs) co d =
-		    first_comment cs (co@["(","*"]) (d+1)
-		  | first_comment (c::cs) co d =
-		    if d>0 then first_comment cs (co@[c]) d
-		    else first_comment cs co d
-		  | first_comment [] _ _ = raise lex_err;
-		    
-	     (* --------------------
-	        The function lc_exists leading comment exists?)
-		checks whether in the input file at the very beginning
-		there is a comment, which needs to be extracted and put
-		into the output file. We also need to check whether there
-		might be a space, a new line or a tab, which do not
-		exclude the possibility that there is a leading comment.
-		The function returns a boolean value. 
-		-------------------- *)
-		fun lc_exists ("("::"*"::_) = true
-		  | lc_exists (" "::cs) = lc_exists cs
-		  | lc_exists ("\n"::cs) = lc_exists cs
-		  | lc_exists ("\t"::cs) = lc_exists cs
-		  | lc_exists _ = false;
-		    
-	     (* --------------------
-	        In the case that there is a leading comment, this
-		function leading_comment extracts it> It also need
-		to check for any html escape sequences in the comment.
-		-------------------- *)
-		fun leading_comment sl =
-		    if (lc_exists sl) then
-			(html_escape (first_comment sl [] 0))
-		    else
-			[""];
-			
-	     (* --------------------
-	        The function thy_name checks for the parent theory
-		names apearing after the leading comment. The function
-		returns a boolean value indicating if the word is a
-		theory name, so that a link can be inserted and can look
-		for another potential theory name. If the word is not a
-		theory name then continue to modify the rest of the body.
-		-------------------- *)
-		fun thy_name word = 
-		    is_some (Symtab.lookup (theory_list, word));
-		    
-	     (* --------------------
-	        Creates the right html format when inserting the link.
-		-------------------- *)
-		fun format_link s = 
-		    let in
-			output(std_out,"\n"^s);
-			"<A HREF = \""^htmlpath^s^".html\">"^s^"</A>"
-		    end;
-
-	     (* --------------------
-		-------------------- *)
-
-		fun insert_link w = (explode (format_link (implode w)))
-	     (* --------------------
-		-------------------- *)
-
-		fun html ( " "::l) r = html l (r@[ " "])
-		  | html ( "+"::l) r = html l (r@[ "+"])
-		  | html ("\n"::l) r = html l (r@["\n"])
-		  | html ("\t"::l) r = html l (r@["\t"])
-		  | html l r = r@(get_word l [])
-	     (* --------------------
-		-------------------- *)
-		and get_word ( " "::l) w = 
-		    if (thy_name (implode w)) 
-			then (insert_link w)@[ " "]@(html l [])
-		    else w@[" "]@(html_escape l)
-		  | get_word ( "+"::l) w = 
-		    if (thy_name (implode w))
-			then (insert_link w)@[ "+"]@(html l [])
-		    else w@["+"]@(html_escape l)
-		  | get_word ("\n"::l) w = 
-		    if (thy_name (implode w))
-			then (insert_link w)@[ "\n"]@(html l [])
-		    else w@["\n"]@(html_escape l)
-		  | get_word ("\t"::l) w = 
-		    if (thy_name (implode w))
-			then (insert_link w)@[ "\t"]@(html l [])
-		    else w@["\t"]@(html_escape l)
-		  | get_word (c::l) w = (get_word l (w@[c]))
-		  | get_word [] [] = []
-		  | get_word [] w = 
-		    if (thy_name (implode w))
-			then (insert_link w)
-		    else w;
-			
-	     (* --------------------
-		-------------------- *)
-		fun modify_body ("="::l) r = r@["="]@(html l [])
-		  | modify_body (c::l) r = modify_body l (r@[c])
-		  | modify_body [] r = r;
-		    
-	     (* --------------------
-		-------------------- *)
-		fun after_first_c ("*"::")"::cs) 1 = cs
-		  | after_first_c ("*"::")"::cs) d = after_first_c cs (d-1)
-		  | after_first_c ("("::"*"::cs) d = after_first_c cs (d+1)
-		  | after_first_c (c::cs) d = after_first_c cs d
-		  | after_first_c cs 0 = cs
-		  | after_first_c [] _ = raise lex_err;
-		    
-	     (* --------------------
-		-------------------- *)
-		fun remove_lc sl =
-		    if (lc_exists sl) then (after_first_c sl 0) else sl;
-			
-	     (* --------------------
-		-------------------- *)
-		fun rest sl = modify_body (remove_lc sl) [];
-		    
-	     (* --------------------
-		-------------------- *)
-		fun filter sl = (leading_comment sl) @ (rest sl);
-		    
-	     (* --------------------
-		-------------------- *)
-		fun getstring s =
-		    case input (is, 1) of
-			"" => head^title^(implode(filter(explode(s))))^tail
-		      | "\n" => getstring (s^"\n")
-		      | c  => getstring (s^c)
-	    in
-		getstring ""
-	    end;
-
-     (* --------------------
-      	-------------------- *)
-	fun transform t =
-	    let
-		val infile = open_in intext;
-		val outfile = open_out outtext
-	    in
-		output(std_out,"\nTheory: "^t);
-		output (outfile, gettext(infile));
-		close_in (infile);
-		close_out (outfile)
-	    end;
-
-     (* --------------------
-      	-------------------- *)
-	fun create_pure p =
-	    let
-		val outfile = open_out outtext
-	    in
-		output(std_out, "\nCreating Pure.html ...");
-		output (outfile, "<HTML>\n<HEAD>\n<TITLE>"^intext^
-			"</TITLE>\n</HEAD>\n\n"^"<BODY>\n"^
-			"<H1>"^tname^".thy"^"</H1></P>\n\n"^"<PRE>\n"^
-			"This is a theory file called Pure.\n"^
-			"Its children are all other Isabelle theories."^
-			"</PRE>"^"</BODY>\n"^"</HTML>");
-		close_out (outfile)
-	    end
-	
-    in
-	if (tname <> "Pure") then (transform tname)
-	else (create_pure tname)
-    end;
-
-(* --------------------
-   -------------------- *)
-map move_eachf (files);
-