src/Pure/proof_general.ML
changeset 15173 e1582a0d29b5
parent 15156 daa9f645a26e
child 15191 5ca1fd9dec83
equal deleted inserted replaced
15172:73069e033a0b 15173:e1582a0d29b5
     5 Isabelle configuration for Proof General (see http://proofgeneral.inf.ed.ac.uk)
     5 Isabelle configuration for Proof General (see http://proofgeneral.inf.ed.ac.uk)
     6 Includes support for PGIP control language for Isabelle/Isar.
     6 Includes support for PGIP control language for Isabelle/Isar.
     7 
     7 
     8 ===========================================================================
     8 ===========================================================================
     9 NOTE: With this version you will lose support for the Isabelle
     9 NOTE: With this version you will lose support for the Isabelle
    10 preferences menu in the currently released version of Proof General (3.5).
    10 settings menu in the currently released version of Proof General (3.5).
    11 No other changes should be visible in the Emacs interface.
    11 No other changes should be visible in the Emacs interface.
    12 
    12 
    13 If the loss of preferences is a serious problem, please use a "sticky"
    13 The 3.6pre pre-release versions of Emacs Proof General now support the 
    14 check-out of the previous version of this file, version 1.27.
    14 new PGIP format for preferences and restore the settings menu.  
    15 
    15 Please visit http://proofgeneral.inf.ed.ac.uk/develdownload
    16 A version of Emacs Proof General which supports the new PGIP format for
       
    17 preferences will be available shortly.  
       
    18 ===========================================================================
    16 ===========================================================================
    19 
    17 
    20 STATUS: this version is an experimental version that supports PGIP 2.X.
    18 STATUS: this version is an experimental version that supports PGIP 2.X.
    21 
    19 
    22 *)
    20 *)
   201  fun assemble_pgip resp attrs s = assemble_pgips [XML.element resp attrs [s]]
   199  fun assemble_pgip resp attrs s = assemble_pgips [XML.element resp attrs [s]]
   202 				  
   200 				  
   203  fun assemble_pgipe resp attrs = assemble_pgips [XML.element resp attrs []]
   201  fun assemble_pgipe resp attrs = assemble_pgips [XML.element resp attrs []]
   204 
   202 
   205  (* FIXME: need to add stuff to gather PGIPs here *)
   203  (* FIXME: need to add stuff to gather PGIPs here *)
   206  fun issue_pgip resp attrs = writeln_default o (assemble_pgip resp attrs)
   204  fun issue_pgip resp attrs txt = 
       
   205      if pgip_emacs_compatibility() then
       
   206 	 decorated_output (* add urgent message annotation *)
       
   207 	     (oct_char "360") (oct_char "361") "" 
       
   208 	     (assemble_pgip resp attrs txt)
       
   209      else 
       
   210 	 writeln_default (assemble_pgip resp attrs txt)
   207 
   211 
   208 (*  FIXME: temporarily to support PG 3.4.  *)
   212 (*  FIXME: temporarily to support PG 3.4.  *)
   209  fun issue_pgip_maybe_decorated bg en resp attrs s = 
   213  fun issue_pgip_maybe_decorated bg en resp attrs s = 
   210      if pgip_emacs_compatibility() then
   214      if pgip_emacs_compatibility() then
   211       (*  in PGIP mode, but using escape characters as well.  *)
   215       (*  in PGIP mode, but using escape characters as well.  *)
   217 
   221 
   218 end
   222 end
   219 
   223 
   220 (* messages and notification *)
   224 (* messages and notification *)
   221 
   225 
   222 fun message resp attrs bg en prfx s =
   226 local
   223   if pgip() then 
   227     val delay_msgs = ref false   (* whether to accumulate messages *)
   224       issue_pgip_maybe_decorated bg en resp attrs (prefix_lines prfx s)
   228     val delayed_msgs = ref []
   225   else 
   229 in
   226       decorated_output bg en prfx s;
   230 
   227 
   231  fun message resp attrs bg en prfx s =
       
   232      if pgip() then 
       
   233 	 (if (!delay_msgs) then
       
   234 	      delayed_msgs := (resp,attrs,prefix_lines prfx s)::(!delayed_msgs) (* nb: no decs *)
       
   235 	  else 
       
   236 	      issue_pgip_maybe_decorated bg en resp attrs (prefix_lines prfx s))
       
   237      else 
       
   238 	 decorated_output bg en prfx s;
       
   239 
       
   240  fun start_delay_msgs () = (delay_msgs := true;
       
   241 			    delayed_msgs := [])
       
   242 
       
   243  fun end_delayed_msgs () = 
       
   244      (delay_msgs := false;
       
   245       map (fn (resp,attrs,s) => XML.element resp attrs [s]) (!delayed_msgs))
       
   246 end
   228 
   247 
   229 local
   248 local
   230     val display_area = ("area", "display")
   249     val display_area = ("area", "display")
   231     val message_area = ("area", "message")
   250     val message_area = ("area", "message")
   232     val tracing_category = ("category", "tracing")
   251     val tracing_category = ("category", "tracing")
   314     fun statedisplay prts =
   333     fun statedisplay prts =
   315 	issue_pgip "proofstate" []
   334 	issue_pgip "proofstate" []
   316 		   (XML.element "pgml" []
   335 		   (XML.element "pgml" []
   317 				[XML.element "statedisplay" 
   336 				[XML.element "statedisplay" 
   318 					     [] 
   337 					     [] 
   319 					     [Output.output (* FIXME: needed? *)
   338 					     [(Pretty.output (Pretty.chunks prts))]])
   320 						  (Pretty.output
       
   321 						       (Pretty.chunks prts))]])
       
   322 
   339 
   323     fun print_current_goals n m st =
   340     fun print_current_goals n m st =
   324 	if pgml () then statedisplay (Display.pretty_current_goals n m st)
   341 	if pgml () then statedisplay (Display.pretty_current_goals n m st)
   325 	else tmp_markers (fn () => Display.print_current_goals_default n m st)
   342 	else tmp_markers (fn () => Display.print_current_goals_default n m st)
   326 	     
   343 	     
   491 in
   508 in
   492 
   509 
   493 fun nat_option r = (pgipnat,
   510 fun nat_option r = (pgipnat,
   494   withdefault (fn () => string_of_int (!r)),
   511   withdefault (fn () => string_of_int (!r)),
   495   (fn s => (case Syntax.read_nat s of
   512   (fn s => (case Syntax.read_nat s of
   496        None => error "nat_option: illegal value"
   513        None => error ("nat_option: illegal value " ^ s)
   497      | Some i => r := i)));
   514      | Some i => r := i)));
   498 
   515 
   499 fun bool_option r = (pgipbool,
   516 fun bool_option r = (pgipbool,
   500   withdefault (fn () => Bool.toString (!r)),
   517   withdefault (fn () => Bool.toString (!r)),
   501   (fn "false" => r := false | "true" => r := true
   518   (fn "false" => r := false | "true" => r := true
   502     | _ => error "bool_option: illegal value"));
   519     | x => error ("bool_option: illegal value" ^ x)));
   503 
   520 
   504 val proof_option = (pgipbool,
   521 val proof_option = (pgipbool,
   505   withdefault (fn () => Bool.toString (!proofs >= 2)),
   522   withdefault (fn () => Bool.toString (!proofs >= 2)),
   506   (fn "false" => proofs := 1 | "true" => proofs := 2
   523   (fn "false" => proofs := 1 | "true" => proofs := 2
   507     | _ => error "proof_option: illegal value"));
   524     | x => error ("proof_option: illegal value" ^ x)));
   508 
   525 
   509 val thm_deps_option = (pgipbool,
   526 val thm_deps_option = (pgipbool,
   510   withdefault (fn () => Bool.toString (Output.has_mode "thm_deps")),
   527   withdefault (fn () => Bool.toString (Output.has_mode "thm_deps")),
   511   (fn "false" => print_mode := ((!print_mode) \ "thm_deps")
   528   (fn "false" => print_mode := ((!print_mode) \ "thm_deps")
   512     | "true" => print_mode := ("thm_deps" ins (!print_mode))
   529     | "true" => print_mode := ("thm_deps" ins (!print_mode))
   513     | _ => error "thm_deps_option: illegal value"));
   530     | x => error ("thm_deps_option: illegal value " ^ x)));
   514 
   531 
   515 local 
   532 local 
   516     val pg_print_depth_val = ref 10
   533     val pg_print_depth_val = ref 10
   517     fun pg_print_depth n = (print_depth n; pg_print_depth_val := n)
   534     fun pg_print_depth n = (print_depth n; pg_print_depth_val := n)
   518 in
   535 in
   519 val print_depth_option = (pgipnat,
   536 val print_depth_option = (pgipnat,
   520   withdefault (fn () => string_of_int (!pg_print_depth_val)),
   537   withdefault (fn () => string_of_int (!pg_print_depth_val)),
   521   (fn s => (case Syntax.read_nat s of
   538   (fn s => (case Syntax.read_nat s of
   522        None => error "print_depth_option: illegal value"
   539        None => error ("print_depth_option: illegal value" ^ s)
   523      | Some i => pg_print_depth i)))
   540      | Some i => pg_print_depth i)))
   524 end
   541 end
   525 
   542 
   526 val preferences = ref 
   543 val preferences = ref 
   527   [("Display",
   544   [("Display",
   749 		    
   766 		    
   750     fun xmls_of_thy_begin (name,toks,str) = (* see isar_syn.ML/theoryP *)
   767     fun xmls_of_thy_begin (name,toks,str) = (* see isar_syn.ML/theoryP *)
   751 	let 
   768 	let 
   752 	    val ((thyname,imports,files),_) = ThyHeader.args (toks@sync)
   769 	    val ((thyname,imports,files),_) = ThyHeader.args (toks@sync)
   753 	in 
   770 	in 
   754 	    markup_text_attrs str "opentheory" [("thyname",thyname)]
   771 	    markup_text_attrs str "opentheory" [("thyname",thyname),
       
   772 						("parentnames", space_implode ";" imports)]
   755 	end 
   773 	end 
   756 
   774 
   757     fun xmls_of_thy_decl (name,toks,str) = (* see isar_syn.ML/thy_decl cases  *)
   775     fun xmls_of_thy_decl (name,toks,str) = (* see isar_syn.ML/thy_decl cases  *)
   758 	let 
   776 	let 
   759 	    (* NB: PGIP only deals with single name bindings at the moment;
   777 	    (* NB: PGIP only deals with single name bindings at the moment;
   888 	  | markup toks x = markup_text (implode (map OuterLex.unparse toks)) x
   906 	  | markup toks x = markup_text (implode (map OuterLex.unparse toks)) x
   889     in
   907     in
   890 	(markup whs "comment") @ (markup rest "unparseable")
   908 	(markup whs "comment") @ (markup rest "unparseable")
   891     end
   909     end
   892     
   910     
       
   911 fun markup_unparseable str = markup_text str "unparseable" 
       
   912 
   893 end
   913 end
   894 
   914 
   895 
   915 
   896 local
   916 local
   897     (* we have to weave together the whitespace/comments with proper tokens 
   917     (* we have to weave together the whitespace/comments with proper tokens 
   903 	else match_tokens (t::ts,ws,w::vs)
   923 	else match_tokens (t::ts,ws,w::vs)
   904       | match_tokens _ = error ("match_tokens: mismatched input parse")
   924       | match_tokens _ = error ("match_tokens: mismatched input parse")
   905 in
   925 in
   906     fun xmls_of_str str =
   926     fun xmls_of_str str =
   907     let 
   927     let 
   908        val toks = OuterSyntax.scan str
       
   909 
       
   910        (* parsing:   See outer_syntax.ML/toplevel_source *)
   928        (* parsing:   See outer_syntax.ML/toplevel_source *)
   911     
       
   912        fun parse_loop ([],[],xmls) = xmls
   929        fun parse_loop ([],[],xmls) = xmls
   913 	 | parse_loop ([],itoks,xmls) = xmls @ (xmls_of_impropers itoks)
   930 	 | parse_loop ([],itoks,xmls) = xmls @ (xmls_of_impropers itoks)
   914 	 | parse_loop ((nm,toks,_)::trs,itoks,xmls) =
   931 	 | parse_loop ((nm,toks,_)::trs,itoks,xmls) =
   915 	   let 
   932 	   let 
   916 	       (* first proper token is command, except FIXME for -- *)
   933 	       (* first proper token is command, except FIXME for -- *)
   926 	       val xmls_tr  = xmls_of_transition (nm,str,toks)
   943 	       val xmls_tr  = xmls_of_transition (nm,str,toks)
   927 	   in
   944 	   in
   928 	       parse_loop(trs,itoks'',xmls @ xmls_whs @ xmls_tr)
   945 	       parse_loop(trs,itoks'',xmls @ xmls_whs @ xmls_tr)
   929 	   end
   946 	   end
   930     in
   947     in
   931 	(* FIXME: put errors/warnings inside the parse result *)
   948 	(let val toks = OuterSyntax.scan str
   932 	parse_loop (OuterSyntax.read toks, toks, [])
   949 	 in 
       
   950 	     parse_loop (OuterSyntax.read toks, toks, [])
       
   951 	 end)
       
   952  	   handle _ => markup_unparseable str
   933     end
   953     end
   934 
   954 
   935 
   955 
   936 fun parsescript str = 
   956 fun parsescript str attrs = 
   937     issue_pgips [XML.element "parseresult" [] (xmls_of_str str)]
   957     let 
   938 
   958 	val _ = start_delay_msgs ()  (* accumulate error messages to put inside parseresult *)
       
   959 	val xmls = xmls_of_str str
       
   960         val errs = end_delayed_msgs ()
       
   961      in 
       
   962 	issue_pgips [XML.element "parseresult" attrs (errs@xmls)]
       
   963     end
   939 end
   964 end
   940 
   965 
   941 
   966 
   942 
   967 
   943 (**** PGIP:  Isabelle -> Interface ****)
   968 (**** PGIP:  Isabelle -> Interface ****)
  1008 	  (* instead of error we could guess theory? *)
  1033 	  (* instead of error we could guess theory? *)
  1009 	  | other => error ("Don't know how to read a file with extension " ^ other)
  1034 	  | other => error ("Don't know how to read a file with extension " ^ other)
  1010     end  
  1035     end  
  1011 
  1036 
  1012 
  1037 
  1013 local
  1038 (* Proof control commands *)
  1014   (* Proof control commands *)
  1039 
  1015 
  1040 local
  1016   fun xmlattro attrs attr = assoc(attrs,attr)
  1041   fun xmlattro attr attrs = assoc(attrs,attr)
  1017 
  1042 
  1018   fun xmlattr attrs attr = 
  1043   fun xmlattr attr attrs = 
  1019       (case xmlattro attrs attr of 
  1044       (case xmlattro attr attrs of 
  1020 	   Some value => value 
  1045 	   Some value => value 
  1021 	 | None => raise PGIP ("Missing attribute: " ^ attr))
  1046 	 | None => raise PGIP ("Missing attribute: " ^ attr))
  1022 
  1047 
  1023   val thyname_attr = "thyname"
  1048   val thyname_attro = xmlattro "thyname"
  1024   val objtype_attr = "objtype"
  1049   val thyname_attr = xmlattr "thyname"
  1025   val name_attr = "name"
  1050   val objtype_attro = xmlattro "objtype"
  1026   val dirname_attr = "dir"
  1051   val objtype_attr = xmlattr "objtype"
       
  1052   val name_attr = xmlattr "name"
       
  1053   val dirname_attr = xmlattr "dir"
  1027   fun comment x = "(* " ^ x ^ " *)"
  1054   fun comment x = "(* " ^ x ^ " *)"
  1028 
  1055 
  1029   (* parse URLs like "file://host/name.thy" *)
  1056   fun localfile_of_url url = (* only handle file:/// or file://localhost/ *)
  1030   (* FIXME: instead of this, extend code in General/url.ML & use that. *)
  1057       case Url.unpack url of
  1031   fun decode_url url = 
  1058 	  (Url.File path) => File.sysify_path path
  1032       (let 
  1059 	| _ => error ("Cannot access non-local URL " ^ url)
  1033 	  val sep = find_index_eq ":" (explode url)
  1060 
  1034  	  val proto = String.substring(url,0,sep)
  1061   val fileurl_of = localfile_of_url o (xmlattr "url")
  1035 	  val hostsep = find_index_eq "/" (drop (sep+3,explode url))
       
  1036 	  val host = String.substring(url,sep+3,hostsep-sep+4)
       
  1037 	  val doc = if (size url >= sep+hostsep+3) then
       
  1038 			String.substring(url,sep+hostsep+4,size url-hostsep-sep-4) 
       
  1039 		    else ""
       
  1040       in 
       
  1041 	  (proto,host,doc)
       
  1042       end) handle Subscript => error ("Badly formed URL " ^ url)
       
  1043  
       
  1044   fun localfile_of_url url =
       
  1045       let
       
  1046 	  val (proto,host,name) = decode_url url
       
  1047       in
       
  1048 	  if (proto = "file" andalso 
       
  1049 	      (host = "" orelse 
       
  1050 	       host = "localhost" orelse 
       
  1051 	       host = (getenv "HOSTNAME")))
       
  1052 	     then name
       
  1053 	  else error ("Cannot access non-local URL " ^ url)
       
  1054       end
       
  1055 
       
  1056   fun fileurl_of attrs = localfile_of_url (xmlattr attrs "url")
       
  1057 
  1062 
  1058   val topthy = Toplevel.theory_of o Toplevel.get_state
  1063   val topthy = Toplevel.theory_of o Toplevel.get_state
  1059   val topthy_name = PureThy.get_name o topthy
  1064   val topthy_name = PureThy.get_name o topthy
  1060 
  1065 
  1061   val currently_open_file = ref (None : string option)
  1066   val currently_open_file = ref (None : string option)
  1062 
       
  1063 in
  1067 in
  1064 
  1068 
  1065 fun process_pgip_element pgipxml = (case pgipxml of 
  1069 fun process_pgip_element pgipxml = (case pgipxml of 
  1066   (XML.Text t) => warning ("Ignored text in PGIP packet: \n" ^ t)
  1070   (XML.Text t) => warning ("Ignored text in PGIP packet: \n" ^ t)
  1067 | (XML.Elem (xml as (elem, attrs, data))) => 
  1071 | (xml as (XML.Elem (elem, attrs, data))) => 
  1068   (case elem of
  1072   (case elem of
  1069        (* protocol config *)
  1073        (* protocol config *)
  1070        "askpgip"  	=> (usespgip (); send_pgip_config ())
  1074        "askpgip"  	=> (usespgip (); send_pgip_config ())
  1071      | "askpgml"  	=> usespgml ()
  1075      | "askpgml"  	=> usespgml ()
  1072      (* proverconfig *)
  1076      (* proverconfig *)
  1073      | "askprefs" 	=> hasprefs ()
  1077      | "askprefs" 	=> hasprefs ()
  1074      | "getpref"  	=> getpref (xmlattr attrs name_attr)
  1078      | "getpref"  	=> getpref (name_attr attrs)
  1075      | "setpref"  	=> setpref (xmlattr attrs name_attr) (xmltext data)
  1079      | "setpref"  	=> setpref (name_attr attrs) (xmltext data)
  1076      (* provercontrol *)
  1080      (* provercontrol *)
  1077      | "proverinit" 	=> isar_restart ()
  1081      | "proverinit" 	=> isar_restart ()
  1078      | "proverexit" 	=> isarcmd "quit"
  1082      | "proverexit" 	=> isarcmd "quit"
  1079      | "startquiet" 	=> isarcmd "disable_pr"
  1083      | "startquiet" 	=> isarcmd "disable_pr"
  1080      | "stopquiet"  	=> isarcmd "enable_pr"
  1084      | "stopquiet"  	=> isarcmd "enable_pr"
  1096      | "undostep"       => isarcmd "ProofGeneral.undo"
  1100      | "undostep"       => isarcmd "ProofGeneral.undo"
  1097      | "abortgoal"      => isarcmd "ProofGeneral.kill_proof"  
  1101      | "abortgoal"      => isarcmd "ProofGeneral.kill_proof"  
  1098      | "forget"         => error "Not implemented" 
  1102      | "forget"         => error "Not implemented" 
  1099      | "restoregoal"    => error "Not implemented"  (* could just treat as forget? *)
  1103      | "restoregoal"    => error "Not implemented"  (* could just treat as forget? *)
  1100      (* proofctxt: improper commands *)
  1104      (* proofctxt: improper commands *)
  1101      | "askids"         => askids (xmlattro attrs thyname_attr, 
  1105      | "askids"         => askids (thyname_attro attrs, objtype_attro attrs)
  1102 				   xmlattro attrs objtype_attr)
  1106      | "showid"	        => showid (thyname_attro attrs, objtype_attr attrs, name_attr attrs)
  1103      | "showid"	        => showid (xmlattro attrs thyname_attr, 
  1107      | "parsescript"    => parsescript (xmltext data) attrs (* just pass back attrs unchanged *)
  1104 				   xmlattr attrs objtype_attr,
       
  1105 		     		   xmlattr attrs name_attr)
       
  1106      | "parsescript"    => parsescript (xmltext data)
       
  1107      | "showproofstate" => isarcmd "pr"
  1108      | "showproofstate" => isarcmd "pr"
  1108      | "showctxt"       => isarcmd "print_theory"   (* more useful than print_context *)
  1109      | "showctxt"       => isarcmd "print_theory"   (* more useful than print_context *)
  1109      | "searchtheorems" => isarcmd ("thms_containing " ^ (xmltext data))
  1110      | "searchtheorems" => isarcmd ("thms_containing " ^ (xmltext data))
  1110      | "setlinewidth"   => isarcmd ("pretty_setmargin " ^ (xmltext data))
  1111      | "setlinewidth"   => isarcmd ("pretty_setmargin " ^ (xmltext data))
  1111      | "viewdoc"	=> isarcmd ("print_" ^ (xmltext data)) (* FIXME: isatool doc? *)
  1112      | "viewdoc"	=> isarcmd ("print_" ^ (xmltext data)) (* FIXME: isatool doc? *)
  1114      | "theoryitem"     => isarscript data
  1115      | "theoryitem"     => isarscript data
  1115      | "closetheory"    => (isarscript data;
  1116      | "closetheory"    => (isarscript data;
  1116 			    writeln ("Theory "^(topthy_name())^" completed."))
  1117 			    writeln ("Theory "^(topthy_name())^" completed."))
  1117      (* improperfilecmd: theory-level commands not in script *)
  1118      (* improperfilecmd: theory-level commands not in script *)
  1118      | "aborttheory"    => isarcmd ("init_toplevel")
  1119      | "aborttheory"    => isarcmd ("init_toplevel")
  1119      | "retracttheory"  => isarcmd ("kill_thy " ^
  1120      | "retracttheory"  => isarcmd ("kill_thy " ^ (quote (thyname_attr attrs)))
  1120 				    (quote (xmlattr attrs thyname_attr)))
  1121      | "loadfile"       => use_thy_or_ml_file (fileurl_of attrs)
  1121      | "loadfile"       => use_thy_or_ml_file    (fileurl_of attrs)
       
  1122      | "openfile"       => (inform_file_retracted (fileurl_of attrs);
  1122      | "openfile"       => (inform_file_retracted (fileurl_of attrs);
  1123 			    currently_open_file := Some (fileurl_of attrs))
  1123 			    currently_open_file := Some (fileurl_of attrs))
  1124      | "closefile"      => (case !currently_open_file of 
  1124      | "closefile"      => (case !currently_open_file of 
  1125 				Some f => (inform_file_processed f;
  1125 				Some f => (inform_file_processed f;
  1126 					   currently_open_file := None)
  1126 					   currently_open_file := None)
  1127 			      | None => raise PGIP ("closefile when no file is open!"))
  1127 			      | None => raise PGIP ("closefile when no file is open!"))
  1128      | "abortfile"      => (currently_open_file := None) (* perhaps error for no file open *)
  1128      | "abortfile"      => (currently_open_file := None) (* perhaps error for no file open *)
  1129      | "changecwd"      => ThyLoad.add_path (xmlattr attrs dirname_attr)
  1129      | "changecwd"      => ThyLoad.add_path (dirname_attr attrs)
  1130      | "systemcmd"	=> isarscript data
  1130      | "systemcmd"	=> isarscript data
  1131      (* unofficial command for debugging *)
  1131      (* unofficial command for debugging *)
  1132      | "quitpgip" => raise PGIP_QUIT  
  1132      | "quitpgip" => raise PGIP_QUIT  
  1133      | _ => raise PGIP ("Unrecognized PGIP element: " ^ elem)))
  1133      | _ => raise PGIP ("Unrecognized PGIP element: " ^ elem)))
  1134 
  1134 
  1135 fun process_pgip_tree s = 
  1135 fun process_pgip_tree xml = 
  1136     (pgip_refseq := None; 
  1136     (pgip_refseq := None; 
  1137      pgip_refid := None;
  1137      pgip_refid := None;
  1138      (case s of
  1138      (case xml of
  1139 	  XML.Elem ("pgip", attrs, pgips) => 
  1139 	  XML.Elem ("pgip", attrs, pgips) => 
  1140 	  (let 
  1140 	  (let 
  1141 	       val class = xmlattr attrs "class"
  1141 	       val class = xmlattr "class" attrs
  1142 	       val _ = (pgip_refseq := xmlattro attrs "seq";
  1142 	       val _ = (pgip_refseq := xmlattro "seq" attrs;
  1143 			pgip_refid :=  xmlattro attrs "id")
  1143 			pgip_refid :=  xmlattro "id" attrs)
  1144 	   in  
  1144 	   in  
  1145 	       if (class = "pa") then
  1145 	       if (class = "pa") then
  1146 		   seq process_pgip_element pgips
  1146 		   seq process_pgip_element pgips
  1147 	       else 
  1147 	       else 
  1148 		   raise PGIP "PGIP packet for me should have class=\"pa\""
  1148 		   raise PGIP "PGIP packet for me should have class=\"pa\""
  1149 	   end)
  1149 	   end)
  1150 	| _ => raise PGIP "Invalid PGIP packet received") 
  1150 	| _ => raise PGIP "Invalid PGIP packet received") 
  1151      handle (PGIP msg) => 
  1151      handle (PGIP msg) => 
  1152 	    (error (msg ^ "\nPGIP error occured in XML text below:\n" ^ 
  1152 	    (error (msg ^ "\nPGIP error occured in XML text below:\n" ^ 
  1153 		    (XML.string_of_tree s))))
  1153 		    (XML.string_of_tree xml))))
  1154 
  1154 
  1155 (* for export to Emacs *)
  1155 (* for export to Emacs *)
  1156 (* val process_pgip = process_pgip_tree o XML.tree_of_string; *)
  1156 (* val process_pgip = process_pgip_tree o XML.tree_of_string; *)
  1157 (* FIXME: for temporary compatibility with PG 3.4, we engage special characters
  1157 (* FIXME: for temporary compatibility with PG 3.4, we engage special characters
  1158    during output *)
  1158    during output *)