226 |
226 |
227 StringLike, STRING (..), TEXT (..), BYTES (..), |
227 StringLike, STRING (..), TEXT (..), BYTES (..), |
228 show_bytes, show_text, |
228 show_bytes, show_text, |
229 |
229 |
230 proper_string, enclose, quote, space_implode, commas, commas_quote, cat_lines, |
230 proper_string, enclose, quote, space_implode, commas, commas_quote, cat_lines, |
231 space_explode, split_lines, trim_line) |
231 space_explode, split_lines, trim_line, |
|
232 |
|
233 getenv, getenv_strict) |
232 where |
234 where |
233 |
235 |
|
236 import System.Environment (lookupEnv) |
|
237 import Data.Maybe (fromMaybe) |
234 import qualified Data.Text as Text |
238 import qualified Data.Text as Text |
235 import Data.Text (Text) |
239 import Data.Text (Text) |
236 import qualified Data.Text.Lazy as Lazy |
240 import qualified Data.Text.Lazy as Lazy |
237 import Data.String (IsString) |
241 import Data.String (IsString) |
238 import qualified Data.List.Split as Split |
242 import qualified Data.List.Split as Split |
3152 |
3171 |
3153 {- server address -} |
3172 {- server address -} |
3154 |
3173 |
3155 localhost_name :: Bytes |
3174 localhost_name :: Bytes |
3156 localhost_name = "127.0.0.1" |
3175 localhost_name = "127.0.0.1" |
|
3176 |
|
3177 localhost_prefix :: Bytes |
|
3178 localhost_prefix = localhost_name <> ":" |
|
3179 |
|
3180 localhost_unprefix :: Bytes -> Maybe Bytes |
|
3181 localhost_unprefix address = |
|
3182 if Bytes.isPrefixOf localhost_prefix address |
|
3183 then Just $ Bytes.drop (Bytes.length localhost_prefix) address |
|
3184 else Nothing |
3157 |
3185 |
3158 localhost :: Socket.HostAddress |
3186 localhost :: Socket.HostAddress |
3159 localhost = Socket.tupleToHostAddress (127, 0, 0, 1) |
3187 localhost = Socket.tupleToHostAddress (127, 0, 0, 1) |
3160 |
3188 |
3161 publish_text :: Bytes -> Bytes -> UUID.T -> Bytes |
3189 publish_text :: Bytes -> Bytes -> UUID.T -> Bytes |
3345 |
3373 |
3346 Params, |
3374 Params, |
3347 get_script, get_input, get_cwd, get_putenv, get_redirect, |
3375 get_script, get_input, get_cwd, get_putenv, get_redirect, |
3348 get_timeout, get_description, |
3376 get_timeout, get_description, |
3349 script, input, cwd, putenv, redirect, timeout, description, |
3377 script, input, cwd, putenv, redirect, timeout, description, |
|
3378 server_run, server_kill, |
|
3379 server_uuid, server_interrupt, server_failure, server_result |
3350 ) |
3380 ) |
3351 where |
3381 where |
3352 |
3382 |
3353 import Text.Printf (printf) |
3383 import Text.Printf (printf) |
3354 import qualified Isabelle.Symbol as Symbol |
3384 import qualified Isabelle.Symbol as Symbol |
3433 timeout :: Time -> Params -> Params |
3463 timeout :: Time -> Params -> Params |
3434 timeout timeout params = params { _timeout = timeout } |
3464 timeout timeout params = params { _timeout = timeout } |
3435 |
3465 |
3436 description :: Bytes -> Params -> Params |
3466 description :: Bytes -> Params -> Params |
3437 description description params = params { _description = description } |
3467 description description params = params { _description = description } |
|
3468 |
|
3469 |
|
3470 {- server messages -} |
|
3471 |
|
3472 server_run, server_kill :: Bytes |
|
3473 server_run = \<open>Bash.server_run\<close>; |
|
3474 server_kill = \<open>Bash.server_kill\<close>; |
|
3475 |
|
3476 server_uuid, server_interrupt, server_failure, server_result :: Bytes |
|
3477 server_uuid = \<open>Bash.server_uuid\<close>; |
|
3478 server_interrupt = \<open>Bash.server_interrupt\<close>; |
|
3479 server_failure = \<open>Bash.server_failure\<close>; |
|
3480 server_result = \<open>Bash.server_result\<close>; |
3438 \<close> |
3481 \<close> |
3439 |
3482 |
3440 generate_file "Isabelle/Process_Result.hs" = \<open> |
3483 generate_file "Isabelle/Process_Result.hs" = \<open> |
3441 {- Title: Isabelle/Process_Result.hs |
3484 {- Title: Isabelle/Process_Result.hs |
3442 Author: Makarius |
3485 Author: Makarius |
3633 Decode.pair Decode.properties (Decode.pair Decode.string (Decode.pair Decode.string Decode.string)) body |
3676 Decode.pair Decode.properties (Decode.pair Decode.string (Decode.pair Decode.string Decode.string)) body |
3634 in (name, Opt { _pos = pos, _name = name, _typ = typ, _value = value }) |
3677 in (name, Opt { _pos = pos, _name = name, _typ = typ, _value = value }) |
3635 in Options . Map.fromList . Decode.list decode_entry |
3678 in Options . Map.fromList . Decode.list decode_entry |
3636 \<close> |
3679 \<close> |
3637 |
3680 |
|
3681 generate_file "Isabelle/Isabelle_System.hs" = \<open> |
|
3682 {- Title: Isabelle/Isabelle_System.hs |
|
3683 Author: Makarius |
|
3684 LICENSE: BSD 3-clause (Isabelle) |
|
3685 |
|
3686 Isabelle system support. |
|
3687 |
|
3688 See \<^file>\<open>~~/src/Pure/System/isabelle_system.ML\<close> |
|
3689 and \<^file>\<open>~~/src/Pure/System/isabelle_system.scala\<close> |
|
3690 -} |
|
3691 |
|
3692 {-# LANGUAGE OverloadedStrings #-} |
|
3693 |
|
3694 module Isabelle.Isabelle_System ( |
|
3695 bash_process, bash_process0 |
|
3696 ) |
|
3697 where |
|
3698 |
|
3699 import Data.Maybe (fromMaybe) |
|
3700 import Control.Exception (throw, AsyncException (UserInterrupt)) |
|
3701 import Network.Socket (Socket) |
|
3702 import Isabelle.Bytes (Bytes) |
|
3703 import qualified Isabelle.Byte_Message as Byte_Message |
|
3704 import qualified Isabelle.Time as Time |
|
3705 import Isabelle.Timing (Timing (..)) |
|
3706 import qualified Isabelle.Options as Options |
|
3707 import qualified Isabelle.Bash as Bash |
|
3708 import qualified Isabelle.Process_Result as Process_Result |
|
3709 import qualified Isabelle.XML.Encode as Encode |
|
3710 import qualified Isabelle.YXML as YXML |
|
3711 import qualified Isabelle.Value as Value |
|
3712 import qualified Isabelle.Server as Server |
|
3713 import qualified Isabelle.Isabelle_Thread as Isabelle_Thread |
|
3714 import Isabelle.Library |
|
3715 |
|
3716 |
|
3717 {- bash_process -} |
|
3718 |
|
3719 absolute_path :: Bytes -> Bytes -- FIXME dummy |
|
3720 absolute_path = id |
|
3721 |
|
3722 bash_process :: Options.T -> Bash.Params -> IO Process_Result.T |
|
3723 bash_process options = bash_process0 address password |
|
3724 where |
|
3725 address = Options.string options "bash_process_address" |
|
3726 password = Options.string options "bash_process_password" |
|
3727 |
|
3728 bash_process0 :: Bytes -> Bytes -> Bash.Params -> IO Process_Result.T |
|
3729 bash_process0 address password params = do |
|
3730 Server.connection port password |
|
3731 (\socket -> do |
|
3732 isabelle_tmp <- getenv "ISABELLE_TMP" |
|
3733 Byte_Message.write_message socket (run isabelle_tmp) |
|
3734 loop Nothing socket) |
|
3735 where |
|
3736 port = |
|
3737 case Server.localhost_unprefix address of |
|
3738 Just port -> make_string port |
|
3739 Nothing -> errorWithoutStackTrace "Bad bash_process server address" |
|
3740 |
|
3741 script = Bash.get_script params |
|
3742 input = Bash.get_input params |
|
3743 cwd = Bash.get_cwd params |
|
3744 putenv = Bash.get_putenv params |
|
3745 redirect = Bash.get_redirect params |
|
3746 timeout = Bash.get_timeout params |
|
3747 description = Bash.get_description params |
|
3748 |
|
3749 run :: Bytes -> [Bytes] |
|
3750 run isabelle_tmp = |
|
3751 [Bash.server_run, script, input, |
|
3752 YXML.string_of_body (Encode.option (Encode.string . absolute_path) cwd), |
|
3753 YXML.string_of_body |
|
3754 (Encode.list (Encode.pair Encode.string Encode.string) |
|
3755 (("ISABELLE_TMP", isabelle_tmp) : putenv)), |
|
3756 Value.print_bool redirect, |
|
3757 Value.print_real (Time.get_seconds timeout), |
|
3758 description] |
|
3759 |
|
3760 kill :: Maybe Bytes -> IO () |
|
3761 kill maybe_uuid = do |
|
3762 case maybe_uuid of |
|
3763 Just uuid -> |
|
3764 Server.connection port password (\socket -> |
|
3765 Byte_Message.write_message socket [Bash.server_kill, uuid]) |
|
3766 Nothing -> return () |
|
3767 |
|
3768 err = errorWithoutStackTrace "Malformed result from bash_process server" |
|
3769 the = fromMaybe err |
|
3770 |
|
3771 loop :: Maybe Bytes -> Socket -> IO Process_Result.T |
|
3772 loop maybe_uuid socket = do |
|
3773 result <- Isabelle_Thread.bracket_resource (kill maybe_uuid) (Byte_Message.read_message socket) |
|
3774 case result of |
|
3775 Just [head, uuid] | head == Bash.server_uuid -> loop (Just uuid) socket |
|
3776 Just [head] | head == Bash.server_interrupt -> throw UserInterrupt |
|
3777 Just [head, msg] | head == Bash.server_failure -> errorWithoutStackTrace $ make_string msg |
|
3778 Just (head : a : b : c : d : lines) | head == Bash.server_result -> |
|
3779 let |
|
3780 rc = the $ Value.parse_int a |
|
3781 elapsed = Time.ms $ the $ Value.parse_int b |
|
3782 cpu = Time.ms $ the $ Value.parse_int c |
|
3783 timing = Timing elapsed cpu Time.zero |
|
3784 n = the $ Value.parse_int d |
|
3785 out_lines = take n lines |
|
3786 err_lines = drop n lines |
|
3787 in return $ Process_Result.make rc out_lines err_lines timing |
|
3788 _ -> err |
|
3789 \<close> |
|
3790 |
3638 export_generated_files _ |
3791 export_generated_files _ |
3639 |
3792 |
3640 end |
3793 end |