module DynamicLinker; // Linkers import DLState; import DynamicLink; from pdRequest import ParseCommandLine; import Request; import gui; import check_types; import encode_dynamic; import decode_dynamic; // 0.8.x import deltaIOState; import deltaEventIO; from handler import InstallDDEHandler; import DynID; import directory_structure; // import ExtFile; // ArgEnv import ArgEnv; Start :: *World -> *World; Start world #! world // if is not first instance then the commandline is copied to first instance of the dynamic linker = case /*is_first_instance*/ True of { True | (FirstInstanceOfServer2 is_first_instance) // init FirstInstance2 #! start_state = default_elemU; #! (_,world) = StartIO [menus, timer] start_state [init_io, system_dependent_initial_io] world; -> world; _ -> world; }; = world where { init_io :: !*DLServerState !*(IOState !*DLServerState) -> !*(!*DLServerState,!*IOState !*DLServerState); init_io s io // no arguments? # cmd_line = getCommandLine; | size cmd_line <= 1 = abort "DynamicLinker needs an argument"; // compatibility mode # option = cmd_line.[1]; | (size cmd_line == 2) && ((option == "/W") || (option == "/w")) # project_name = cmd_line.[2]; // read environments # application_path = (ParseCommandLine GetDynamicLinkerPath).[0]; # (sep_found,sep_index) = CharIndexBackwards application_path (size application_path - 1) path_separator; | not sep_found = abort ("could not read IDEEnvs"); # application_path = application_path % (0,dec sep_index); # s = { s & application_path = application_path , static_application_as_client = (option == "/W") || (option == "/w") }; # (s,io) = InitServerState s io; = (s,io); #! dynamic_linker_dir = fst (ExtractPathAndFile cmd_line.[0]); # s = { s & dlss_lib_mode = True , dlss_lib_command_line = cmd_line // set application path , application_path = dynamic_linker_dir }; # (s,io) = InitServerState s io; # (_,io) = ds_create_directory DS_SYSTEM_DYNAMICS_DIR dynamic_linker_dir io; = (s,io); where { build_cmdline_in_addclient_format :: !Int !Int {{#Char}} -> {#Char}; build_cmdline_in_addclient_format i limit cmd_line | i == limit = ""; = cmd_line.[i] +++ (if (i == (dec limit)) "" " ") +++ (build_cmdline_in_addclient_format (inc i) limit cmd_line); }; menus::.(DeviceSystem *DLServerState *(IOState *DLServerState)); menus = MenuSystem [ PullDownMenu file_menu_id "File" Able [ MenuItem quit_id "Quit" (Key 'Q') Able (\s io -> (s,QuitIO io)) ] ]; timer::.(DeviceSystem *DLServerState *(IOState *DLServerState)); timer = TimerSystem [Timer timer_id Able 0 (\q s io -> any_clients_left (t2 s io))]; [file_menu_id,quit_id:_] = [1..]; system_dependent_initial_io = InstallDDEHandler openDDE; where { openDDE file_name = abort ("openDDE: " +++ file_name); } } // windows specific t2 s=:{quit_server,dlss_lib_mode=True,dlss_lib_command_line} io // matches only when there is no other dynamic rts running # s = { s & dlss_lib_mode = False }; #! (timeout,_,_) = ReceiveReqWithTimeOutE True; | timeout || not timeout # (remove_state,client_id,s,io) = AddClient3 DefaultProcessSerialNumber [ arg \\ arg <-: dlss_lib_command_line] s io; = HandleRequestResult (remove_state,client_id,s,io); t2 s=:{quit_server,static_application_as_client} io #! (timeout,client_id,request_name) = ReceiveReqWithTimeOutE static_application_as_client; | timeout = (s,io); #! s = { s & static_application_as_client = False }; #! requests = filter (\(_,name,_) -> (fst (starts name request_name))) RequestList; | (length requests) == 1 // extract arguments and execute request #! request = hd requests; #! request_args = case (fst3 request) of { True -> tl (ExtractArguments '\n' 0 request_name []); False #! index = size (snd3 request); -> [request_name % (index, size request_name - 1)]; }; // do request #! (remove_state,client_id,s,io) = (thd3 (hd requests)) client_id request_args s io; = HandleRequestResult (remove_state,client_id,s,io); #! (s,io) = error ["incoming request '" +++ request_name +++ "' unknown (" +++ toString (size request_name) +++ ")" +++ "\nInternal error"] s io; = (s,io); where { // If requests have common prefixes, then the first request with the common prefix is used. RequestList = [ // eagerly linked applications (True,"AddAndInit",AddAndInitPC) // (is_special,STRING id,function handling request) // compute address descriptor table using the descriptor usage set , (False,"Compute2DescAddressTable",ComputeDescAddressTable2) // get address of the graph to string function , (False,"GetGraphToStringFunction",GetGraphToStringFunction) // closing client , (True,"Close",Close) // general , (True,"Quit",Quit) // send by second or later instance of dynamic rts to first instance of dynamic rts , (False,"MessageFromSecondOrLaterLinker",MessageFromSecondOrLaterLinker) // send to get extra dynamic rts information , (False,"GetDynamicRTSInfo",GetDynamicRTSInfo) // check type definitions , (False,"CheckTypeDefinitions",CheckTypeDefinitions) // Loads an application from a library , (True,"LibInit",LoadApplication) // dumpDynamic is the caller , (False,"DumpDynamic",DumpDynamic) // adding addresses , (False,"GetLabelAddresses",GetLabelAddresses) // register lazy dynamic , (False,"RegisterLazyDynamic",RegisterLazyDynamic) // dumpDynamic is the caller , (False,"GetDynamicLinkerDir",GetDynamicLinkerDir) ]; } any_clients_left (s=:{quit_server,global_client_window={visible_window_ids}},io) // update window #! (no_more_clients,s) = acc_dl_client_states is_empty s; #! (static_application_as_client,s) = s!static_application_as_client; | (not no_more_clients || static_application_as_client || (not (isEmpty visible_window_ids))) && (not quit_server) = (s,io); = (s,QuitIO io); where { is_empty [] = (True,[]); is_empty l = (False,l); }