(* HCoop Domtool (http://hcoop.sourceforge.net/) * Copyright (c) 2006, Adam Chlipala * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *) (* Main interface *) structure Main :> MAIN = struct open Ast Print structure SM = StringMap val dmy = ErrorMsg.dummyLoc fun init () = (F_OpenSSL_SML_add_all_algorithms.f' (); F_OpenSSL_SML_load_error_strings.f' (); F_OpenSSL_SML_load_BIO_strings.f' ()) val () = init () val defaultT : record ref = ref SM.empty val defaultV : (unit -> exp) SM.map ref = ref SM.empty fun registerDefault (name, t, v) = case SM.find (!defaultT, name) of NONE => (defaultT := SM.insert (!defaultT, name, t); defaultV := SM.insert (!defaultV, name, v)) | SOME _ => raise Fail "Duplicate default environment variable" fun tInit () = (TAction ((CRoot, dmy), !defaultT, StringMap.empty), dmy) fun check' G fname = let (*val _ = print ("Check " ^ fname ^ "\n")*) val prog = Parse.parse fname in if !ErrorMsg.anyErrors then G else Tycheck.checkFile G (tInit ()) prog end fun basis () = let val dir = Posix.FileSys.opendir Config.libRoot fun loop files = case Posix.FileSys.readdir dir of NONE => (Posix.FileSys.closedir dir; files) | SOME fname => if String.isSuffix ".dtl" fname then loop (OS.Path.joinDirFile {dir = Config.libRoot, file = fname} :: files) else loop files val files = loop [] val files = Order.order files in if !ErrorMsg.anyErrors then Env.empty else foldl (fn (fname, G) => check' G fname) Env.empty files end fun check fname = let val _ = ErrorMsg.reset () val _ = Env.preTycheck () val b = basis () in if !ErrorMsg.anyErrors then (b, NONE) else let val _ = ErrorMsg.reset () val prog = Parse.parse fname in if !ErrorMsg.anyErrors then (Env.empty, NONE) else let val G' = Tycheck.checkFile b (tInit ()) prog in (G', #3 prog) end end end fun reduce fname = let val (G, body) = check fname in if !ErrorMsg.anyErrors then NONE else case body of SOME body => let val body' = Reduce.reduceExp G body in (*printd (PD.hovBox (PD.PPS.Rel 0, [PD.string "Result:", PD.space 1, p_exp body']))*) SOME body' end | _ => NONE end fun eval fname = case reduce fname of (SOME body') => if !ErrorMsg.anyErrors then () else Eval.exec (SM.map (fn f => f ()) (!defaultV)) body' | NONE => () val dispatcher : C.rw ZString.zstring' = ZString.dupML' Config.dispatcher fun ssl_err s = let val err = F_OpenSSL_SML_get_error.f () in print s; print "\nReason: "; print (ZString.toML (F_OpenSSL_SML_lib_error_string.f err)); print ":"; print (ZString.toML (F_OpenSSL_SML_func_error_string.f err)); print ":"; print (ZString.toML (F_OpenSSL_SML_reason_error_string.f err)); print "\n" end exception OpenSSL of string fun writeAll (bio, s) = let val buf = ZString.dupML' s fun loop (buf, len) = let val r = F_OpenSSL_SML_write.f' (bio, C.Ptr.inject' buf, len) in if r = len then () else if r <= 0 then (C.free' buf; raise OpenSSL "BIO_write failed") else loop (C.Ptr.|+! C.S.uchar (buf, Int32.toInt r), Int32.- (len, r)) end in loop (buf, Int32.fromInt (size s)); C.free' buf end fun request fname = let val bio = F_OpenSSL_SML_new_connect.f' dispatcher in if C.Ptr.isNull' bio then (ssl_err ("Error initializating connection to dispatcher at " ^ Config.dispatcher); F_OpenSSL_SML_free_all.f' bio) else if F_OpenSSL_SML_do_connect.f' bio <= 0 then (ssl_err ("Error connecting to dispatcher at " ^ Config.dispatcher); F_OpenSSL_SML_free_all.f' bio) else let val inf = TextIO.openIn fname fun loop () = case TextIO.inputLine inf of NONE => () | SOME line => (writeAll (bio, line); loop ()) in loop (); TextIO.closeIn inf; F_OpenSSL_SML_free_all.f' bio end end end