1% ---------------------------------------------------------------------- 2% BEGIN LICENSE BLOCK 3% Version: CMPL 1.1 4% 5% The contents of this file are subject to the Cisco-style Mozilla Public 6% License Version 1.1 (the "License"); you may not use this file except 7% in compliance with the License. You may obtain a copy of the License 8% at www.eclipse-clp.org/license. 9% 10% Software distributed under the License is distributed on an "AS IS" 11% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See 12% the License for the specific language governing rights and limitations 13% under the License. 14% 15% The Original Code is The ECLiPSe Constraint Logic Programming System. 16% The Initial Developer of the Original Code is Cisco Systems, Inc. 17% Portions created by the Initial Developer are 18% Copyright (C) 1999-2006 Cisco Systems, Inc. All Rights Reserved. 19% 20% Contributor(s): IC-Parc, Imperal College London 21% 22% END LICENSE BLOCK 23% 24% 25% ECLiPSe II debugger -- Tcl/Tk Interface 26% 27% System: ECLiPSe Constraint Logic Programming System 28% Version: $Id: tracer_tcl.pl,v 1.14 2013/02/23 00:23:18 jschimpf Exp $ 29% Authors: Joachim Schimpf, IC-Parc 30% Kish Shen, IC-Parc 31% Josh Singer, Parc Technologies 32% 33%---------------------------------------------------------------------- 34 35:- module(tracer_tcl). 36 37:- local 38 struct(inspect(type,top,path,written,module)), 39 struct(dg_filter(traceonly, spiedonly, wakeonly)), 40 struct(mfile(dir,module,file)), 41 struct(minfo(interface,comments)), 42 43 reference(exec_state), 44 reference(matdisplaydata), 45 46 variable(observed_count), 47 variable(filter_spy_goal), 48 variable(filter_status), 49 variable(filter_count), 50 variable(filter_hits), 51 variable(inspect_observed), 52 variable(next_cmd), 53 variable(indent_step), 54 variable(dbg_format_string), 55 variable(dbg_goal_format_string), 56 variable(dbg_print_depth), 57 variable(matdisplayid), 58 variable(lbpath_type), 59 variable(library_info), 60 variable(show_module), 61 variable(tracer_command). 62 63 64 65:- setval(matdisplayid,0). 66:- setval(observed_count,0). 67:- setval(inspect_observed, []). 68:- setval(filter_spy_goal, none). 69:- setval(filter_status, off). 70:- setval(filter_count, 1). 71:- setval(filter_hits, 0). 72:- setval(tracer_command, "c"). 73 74% the types for each level of the path used by the library browser 75:- setval(lbpath_type, [top,dir,module,interface]). 76 77:- export 78 init_library_info/0, 79 init_toplevel_module/0, 80 expand_lbnode/2, 81 lbnode_display/3, 82 lbnode_info/4, 83 lbnode_loadmodule/1, 84 return_html_root/1, 85 report_stats/2, 86 stop_report_stats/0, 87 start_report_stats_text_summary/1, 88 stop_report_stats_text_summary/0, 89 change_report_interval/1, 90 inspect_command/3, 91 inspect_get_children_for_path/5, 92 compile_string/1, 93 get_tracer_output_modes/1, set_tracer_output_modes/1, 94 get_tracer_print_depth/1, set_tracer_print_depth/1, 95 compile_os_file/2, 96 use_module_os/2, 97 list_files/1, 98 list_modules/2, 99 list_predicates/4, 100 set_flag_string/4, 101 gui_help_string/2, 102 gui_dg/3, 103 get_triggers/1, 104 get_source_info/4, 105 flag_value/4, 106 record_source_file/1, 107 register_inspected_term/2, 108 make_display_matrix_body/6, 109 make_display_matrix_body/3, 110 kill_display_matrix_body/2, 111 install_guitools/0, 112 uninstall_guitools/0, 113 get_ancestors/1, 114 get_current_traceline/4, 115 get_goal_info_by_invoc/8, 116 prepare_filter/1, 117 set_usepred_info/5, 118 reenable_usepred/0, 119 set_tracer_command/1, 120 toggle_source_breakpoint/5, 121 file_is_readable/1, 122 read_file_for_gui/1, 123 breakpoints_for_file/4, 124 find_exact_callinfo/3, 125 find_matching_callinfo/4, 126 is_current_goal/2, 127 saros_get_library_path/1, 128 saros_set_library_path/1, 129 saros_compile/1, 130 saros_fcompile/2, 131 saros_icompile/2, 132 saros_eci_to_html/3, 133 saros_ecis_to_htmls/4, 134 saros_cd/1, 135 saros_use_module/1, 136 saros_get_goal_info_by_invoc/10. 137 138:- reexport 139 current_files_with_port_lines/1 140 from sepia_kernel. 141 142 143%---------------------------------------------------------------------- 144:- pragma(system). 145:- pragma(nodebug). 146 147%:- import struct(tf), struct(trace_line) from sepia_kernel. 148:- import sepia_kernel. 149 150:- import 151 set_default_error_handler/2, 152 configure_prefilter/5, 153 cut_to_stamp/2, 154 trace_mode/2, 155 find_goal/3, 156 get_attribute/3, 157 get_tf_prop/3, 158 current_predicate_with_port/4, 159 get_portlist_from_file/4, 160 find_matching_breakport/6, 161 stack_overflow_message/1 162 from sepia_kernel. 163 164:- lib(development_support). 165 166:- setval(dbg_goal_format_string, "%*GQPmw"). 167:- setval(dbg_print_depth, 5). 168:- setval(show_module, off). 169:- setval(indent_step, 0). 170 171 172%---------------------------------------------------------------------- 173% Tracer/GUI interface 174% We use two queues to communicate with the GUI 175%---------------------------------------------------------------------- 176 177trace_start_handler_tcl :- 178 setval(filter_status, off), 179 setval(filter_hits, 0), 180 setval(filter_counts, 1), 181 ( peer_queue_get_property(debug_traceline, peer_name, Name), 182 peer_get_property(Name, language, "java") -> 183 /* this is a hopefully temporary way to detect we are using Saros 184 and avoid making changes to the Java side for now 185 */ 186 true 187 ; 188 % inform GUI of start of tracing 189 write_exdr(debug_traceline, []), 190 flush(debug_traceline) 191 ). 192 193 194trace_line_handler_tcl(_, Current) :- 195 % call the goal_filter goal, which represents the user's "conditional 196 % breakpoint. Do this FIRST for speed!!! 197 getval(filter_status, FilterStatus), 198 do_filter(FilterStatus, Current), 199 % make sure the debug_traceline stream is usable, otherwise fail 200 (get_stream_info(debug_traceline, usable, on) -> 201 % usable off only applies if stream performs a yield/2, but for 202 % remote peer queues, this yeild is not done, and can be handled 203 true ; peer_queue_get_property(debug_traceline, peer_type, remote) 204 ), 205 % store the current trace line in a global reference, where it 206 % can be picked up by some of the interactive tools 207 setval(exec_state, Current), 208 % if the goal_filter goal succeeds, we do not want to use the 209 % other clause of trace_line_handler_tcl, which does nothing. 210 !, 211 flush(debug_output), 212 open(string(""), write, SS), 213 make_trace_line(SS, Current, Depth, Port, Invoc, Prio, FPath, _Linum, From0, To0), 214 get_stream_info(SS, name, Line), 215 close(SS), 216 port_style(Port, Style), 217 check_if_source_should_update(Port, From0, To0, From, To), 218 write_exdr(debug_traceline, [Depth, Style, Line, Invoc, Port, Prio, 219 FPath, From, To]), 220 flush(debug_traceline), % may not work in nested emulator... 221 peer_do_multitask(tracer), 222 getval(tracer_command, Cmd), 223 %writeln(error, got:Cmd), 224 %writeln(error, current:Current), 225 interpret_command(Cmd, Current, Depth, Cont), 226 call(Cont), % may cut_to/fail 227 getval(inspect_observed, Obs), 228 setval(inspect_observed, []), % reset 229 create_observed(Obs, Current). 230trace_line_handler_tcl(_,_). 231 232% Prepare for the filter command 233prepare_filter(Count) :- 234 setval(filter_status, on), 235 setval(filter_count, Count). 236 237do_filter(off, _). 238do_filter(on, _) :- 239 filter_count_and_reset(none). 240do_filter(goal(SpyStatus), trace_line{frame:tf{goal:Goal, module:Module}}):- 241 goal_filter(Goal, Module), 242 filter_count_and_reset(SpyStatus). 243 244filter_count_and_reset(SpyStatus) :- 245 incval(filter_hits), 246 getval(filter_count, FCount), 247 (FCount > 1 -> 248 decval(filter_count), 249 fail 250 ; 251 reset_usepred_info(SpyStatus) 252 ), 253 setval(filter_status, off). 254 255make_trace_line(Stream, trace_line{port:Port, frame:Frame}, Depth, 256 Port, Invoc, Prio, FPath, Linum, From, To) :- 257 Frame = tf{invoc:Invoc,goal:Goal,depth:Depth,prio:Prio,module:M, 258 path:Path0, line:Linum, from:From, to:To}, 259 register_inspected_term(Goal, M), 260 % wrapper around pathname to avoid empty string 261 (Path0 == '' -> 262 FPath = no 263 ; 264 os_file_name(Path0, OSPath), 265 FPath = p(OSPath) 266 ), 267 % print priority only if not the normal 12 268 (Prio == 12 -> PrioS = "" ; concat_string([<,Prio,>], PrioS)), 269 ( get_tf_prop(Frame, skip, on) -> Prop = 0'S ; Prop = 0' ), 270 ( get_tf_prop(Frame, break) =\= 0 -> Spied = 0'# 271 ; get_tf_prop(Frame, spy, on) -> Spied = 0'+ ; Spied = 0' ), 272 Indent is Depth*getval(indent_step), 273 printf(Stream, "%c%c%*c(%d) %d %A%s ", 274 [Prop, Spied, Indent, 0' , Invoc, Depth, Port, PrioS]), 275 ( getval(show_module,on) -> MGoal = Goal@M ; MGoal = Goal ), 276 getval(dbg_goal_format_string, Format), 277 getval(dbg_print_depth, PDepth), 278 printf(Stream, Format, [PDepth,MGoal])@M. 279 280 281:- mode port_style(+,-). 282port_style(fail, "fail_style") :- !. 283% Next line leads to not printing LEAVE in stack display. Use separate style? 284%port_style(leave, "fail_style") :- !. 285port_style(exit, "exit_style") :- !. 286port_style('*exit', "exit_style") :- !. 287port_style(_, "call_style"). 288 289% set From/To to -1 if source display should not be updated to new positions 290:- mode check_if_source_should_update(+,+,+,-,-). 291check_if_source_should_update(next, _, _, -1, -1) :- !. 292check_if_source_should_update(else, _, _, -1, -1) :- !. 293check_if_source_should_update(_, From, To, From, To). 294 295set_tracer_command(Cmd) :- 296 setval(tracer_command, Cmd). 297 298:- mode interpret_command(+,+,+,-). 299interpret_command("a", CurrentPort, _, Cont) :- !, 300 trace_mode(5, 0), 301 ( CurrentPort = trace_line{port:leave} -> 302 % don't abort, we may not have any catching block! 303 % turn it into a creep instead... 304 Cont = true 305 ; 306 Cont = abort 307 ). 308interpret_command("l", _, _, true) :- !, trace_mode(2, []). 309interpret_command("filter", _, _, true) :- !. % filter set, just continue 310interpret_command("s", _, Depth, true) :- !, trace_mode(3, Depth). 311interpret_command("n", _, _, true) :- !, trace_mode(5, 0). 312interpret_command("N", _, _, true) :- !, trace_mode(5, 0), 313 set_flag(debugging,nodebug). 314interpret_command("c", _, _, true) :- !, trace_mode(0, []). 315interpret_command("i", _, _, true) :- !. 316interpret_command("j", _, _, true) :- !. 317interpret_command(f(N), Current, _, Cont) :- !, 318 Current = trace_line{port:Port,frame:Stack}, 319 ( Port \== fail, Port \== leave, find_goal(N, Stack, Frame) -> 320 Cont = (cut_to_stamp(Frame, chp of tf),fail) 321 ; 322 Cont = true % already failing or frame not found 323 ). 324interpret_command("z", Current, _, true) :- !, % zap to different port 325 Current = trace_line{port:Port}, 326 configure_prefilter(_, _, ~Port, _, dont_care). 327interpret_command("", _, _, true) :- !. % no command, continue as before 328 329 330%---------------------------------------------------------------------- 331% Filter goal setup 332%---------------------------------------------------------------------- 333 334% initial (empty) breakpoint condition 335goal_filter(_,_). 336 337reset_usepred_info(none) :- !. 338reset_usepred_info(PreviousSpyStatus) :- 339 % there is an active filter goal.... 340 % set the spy status of the template predicate to its previous 341 % state 342 % if no defining module, set on whatever predicate is visible 343 % from here 344 getval(filter_spy_goal,DefiningModule:TemplatePredSpec), 345 (var(DefiningModule) -> 346 set_flag(TemplatePredSpec, spy, PreviousSpyStatus) 347 ; 348 set_flag(TemplatePredSpec, spy, PreviousSpyStatus)@DefiningModule 349 ). 350 351 352set_usepred_info(PredMatchString, PredModuleString, PredDefModuleString, PredConditionString, Status):- 353 !, 354 % parse the defining module 355 term_string(DefiningModule, PredDefModuleString), 356 % construct and compile the condition 357 concat_string(["goal_filter((", PredMatchString, 358 "),(", PredModuleString, 359 ")) ?- catch(\\+(\\+ (", PredConditionString,")), _, fail)"], 360 PredMatchConditionString), 361 % DefiningModule cannot be a variable! 362 term_string(NewGoalFilter, PredMatchConditionString)@DefiningModule, 363 compile_term(NewGoalFilter), 364 % Find the template's functor and arity 365 NewGoalFilter = (goal_filter(Template,_) ?- _), 366 (var(Template) -> 367 Status = none, 368 setval(filter_status, goal(none)), 369 setval(filter_spy_goal, none) 370 ; 371 functor(Template, TemplateFunctor, TemplateArity), 372 % compose its PredSpec out of this. 373 TemplatePredSpec = TemplateFunctor/TemplateArity, 374 % get the spy status of the template predicate 375 % if no defining module, look at whatever is visible from here 376 % fails if module or predicate does not currently exist 377 (set_spy_status(TemplatePredSpec, DefiningModule) -> 378 % record the PredSpec, DefiningModule in a local variable 379 setval(filter_spy_goal,DefiningModule:TemplatePredSpec), 380 Status = spy_set 381 ; 382 setval(filter_spy_goal, none), 383 setval(filter_status, off), 384 Status = not_found 385 ) 386 ). 387 388 389set_spy_status(TemplatePredSpec, DefiningModule) :- 390 find_pred_spyinfo(TemplatePredSpec, DefiningModule, PreviousSpyStatus), 391 setval(filter_status, goal(PreviousSpyStatus)), 392 % set a spypoint on the template predicate 393 % The point of this is that if the template option is 394 % used , and a spypoint is put on the template predicate, 395 % no other predicates need be examined, only spied ones. 396 % Therefore an efficiency advantage is gained. 397 % if no defining module, set one on whatever is visible from here 398 set_flag(TemplatePredSpec, spy, on)@DefiningModule. 399 400reenable_usepred :- 401 (getval(filter_spy_goal, DefiningModule:PredSpec) -> 402 % set_spy_status/2 should not fail here as PredSpec must exist 403 set_spy_status(PredSpec, DefiningModule) 404 ; 405 setval(filter_status, goal(none)) 406 ). 407 408find_pred_spyinfo(TemplatePredSpec, DefiningModule, PreviousSpyStatus) :- 409 (var(DefiningModule) -> 410 get_flag(TemplatePredSpec, spy, PreviousSpyStatus) 411 ; 412 current_module(DefiningModule), 413 get_flag(TemplatePredSpec, spy, PreviousSpyStatus)@DefiningModule 414 ). 415 416%---------------------------------------------------------------------- 417% Inspect subterm stuff 418%---------------------------------------------------------------------- 419 420:- local reference(inspect_object). 421 422 423% eventually these will allow inspect of more than one term 424register_inspected_term(Term, Module) :- 425 setval(inspect_object, f(Term, Module)), 426 true. 427 428 429get_inspected_term(current, Term, Module) :- 430 ( getval(inspect_object, f(Term,Module)) -> 431 true 432 ; 433 Term = 'No term registered for inspection', 434 get_flag(toplevel_module, Module) 435 ). 436get_inspected_term(invoc(N), Goal, Module) :- 437 find_goal_by_invoc(N, _LookupModule, Goal, Module, _, _, _, _). 438get_inspected_term(display(I,R,C), Term, Module) :- 439 get_matrix_term(I, R, C, Term, Module). 440 441 442inspect_command(SourceS, Command, Reply) :- 443 term_string(Source, SourceS), 444 get_inspected_term(Source, Term, Module), 445 process_inspect_command(Command, Term, Reply, Module). 446 447 448process_inspect_command(end, _Term, _, _M) ?- !. 449% exit inspect term. Nothing to be done for now 450process_inspect_command(info(Depth,["1"|Path]), Term, Reply, M) ?- !, 451% provides a normal printable version and summary of the term with Path. 452% merged previous summary and display commands; this allows more flexibility 453% on the Tcl side for how subterms are processed. 454 provide_subterm(Path, Depth, Term, Reply, M). 455process_inspect_command(record_observed(SSource,["1"|Path],Label), _, _Reply, _M) ?- !, 456% make a record of a term that is to be observed 457 term_string(Source, SSource), 458 getval(inspect_observed, ToBeObs), 459 setval(inspect_observed, [o(Source,Path,Label)|ToBeObs]). 460process_inspect_command(movepath(up,N,["1"|Path]), _Term, Reply, _M) ?- !, 461% moves the current subterm up 462 reverse(Path, RPath), 463 move_up(N, RPath, Reply). 464process_inspect_command(movepath(Dir,N,["1"|Path]), Term, Reply, M) ?- !, 465% moves the current subterm to the left or right 466 move_sideways(Dir, N, Path, Term, Reply, M). 467process_inspect_command(select(SourceS), _, Reply, _) ?- !, 468% change the inspected item (in Tcl; here just checks that item is valid) 469 term_string(Source, SourceS), 470 (get_inspected_term(Source, _, _) -> 471 Reply = "ok" ; Reply = "failed" 472 ). 473process_inspect_command(childnodes(Type,Arity,LSize,["1"|Path]), Term, Reply, Module) ?- !, 474/* returns `position' information for the children of all inspector's nodes 475 These nodes are of different ECLiPSe types, and the `positions' 476 can be in a special format which can then be used both by the 477 Tcl and Prolog sides to take special actions in interpreting the path 478 and presenting the children. 479 Type + Arity are the type and arity of the node; LSize is the current 480 threshold length for treating list specially 481*/ 482 provide_childnodes(Type, Path, Term, Arity, LSize, Reply, Module). 483process_inspect_command(modify(PositionS), _, Modifier, _) ?- !, 484/* checks to see if the name of an item needs to be modified because of its 485 position 486*/ 487 term_string(Position, PositionS), 488 position_modifier(Position, Modifier). 489process_inspect_command(translate(PositionS), _, Reply, _) ?- 490/* translate a special position in the internal path format (e.g. 1=foo) to 491 a more readable format for Tcl to print out (e.g. 1 (filedname: foo) 492*/ 493 term_string(Pos, PositionS), 494 translate_pos(Pos, Reply). 495 496 497translate_pos(N=Field, Out) ?- 498 integer(N), !, 499 (integer(Field) -> 500 concat_string(["structure arg#", N], Out) 501 ; concat_string(["Named structure arg, fieldname:", Field], Out) 502 ). 503translate_pos(N-Attr, Out) ?- 504 integer(N), !, 505 concat_string(["attribute name:", Attr], Out). 506translate_pos(list(N), Out) ?- 507 integer(N), !, 508 concat_string(["List element (pos: ", N, ")"], Out). 509translate_pos(tail(N), Out) ?- 510 integer(N), !, 511 concat_string(["List tail (pos: ", N, ")"], Out). 512translate_pos(N, Out) :- 513 integer(N), !, 514 concat_string(["structure arg#", N], Out). 515translate_pos(Pos, Out) :- 516 open("", string, S), 517 printf(S, "unknown position type: %w", [Pos]), 518 get_stream_info(S, name, Out), 519 close(S). 520 521 522provide_childnodes(attributed, Path, Term, _, _, Reply, Module) ?- !, 523 get_subterm_from_path(Path, Term, Term, AVar, Module), 524 valid_attributes_listing(AVar, Reply). 525provide_childnodes(ncompound, Path, Term, Arity, _, Reply, Module) ?- !, 526 get_subterm_from_path(Path, Term, Term, Sub, Module), 527 named_structure(Sub, Module, Defs, Arity), 528 (foreacharg(Name, Defs), count(I, 1, _), foreach(NameSpec, Reply) do 529 term_string(I=Name, NameSpec) 530 ). 531provide_childnodes(list, Path, Term, _, LSize, Reply, Module) ?- !, 532 get_subterm_from_path(Path, Term, Term, Sub, Module), 533 provide_listnodes(Sub, 1, LSize, Reply, Module). 534provide_childnodes(compound, _Path, _Term, Arity, LSize, Reply, _Module) ?- !, 535 % just use arity given to avoid cost of finding subterm 536 (Arity > LSize -> % add argument position if > LSize 537 (for(I, 1, Arity), foreach(PosSpec, Reply) do 538 term_string(I=I, PosSpec) 539 ) 540 ; (for(I, 1, Arity), foreach(I, Reply) do true) 541 ). 542provide_childnodes(scheduled, _, _, _, _, Reply, _) ?- !, 543 Reply = [1]. 544provide_childnodes(suspended, _, _, _, _, Reply, _) ?- !, 545 Reply = [1]. 546provide_childnodes(exphandle, _, _, _, _, Reply, _) ?- !, 547 Reply = [1]. 548provide_childnodes(_Others, _, _, _, _, Reply, _) :- 549 Reply = []. 550 551 552provide_listnodes(List, ListPos0, LSize, Reply, Module) :- 553 List = [_|Tail], 554 ListPos1 is ListPos0 + 1, 555 term_string(list(ListPos0), Pos0S), 556 get_type(Tail, TType, Module), 557 ((TType == list, ListPos0 < LSize) -> 558 Reply = [Pos0S|Reply1], 559 provide_listnodes(Tail, ListPos1, LSize, Reply1, Module) 560 ; term_string(tail(ListPos1), Pos1S), 561 Reply = [Pos0S,Pos1S] 562 ). 563 564move_sideways(Dir, N, Path, Term, Reply, Mod) :- 565 (get_parent_path(Path, PPath, Pos, ArgNo0) -> 566 get_subterm_from_path(PPath, Term, Term, Parent, Mod), 567 (Dir == right -> ArgNo is ArgNo0 + N ; ArgNo is ArgNo0 - N), 568 get_sibling_arg(Pos, ArgNo, PPath, Parent, Mod, NewPath, Status) 569 570 ; % can't get parent 571 Status = "false" 572 ), 573 (Status == "false" -> NewPath = Path ; true), 574 Reply = [Status,["1"|NewPath]]. % add back the root node 575 576 577get_sibling_arg(Pos=FName0, ArgNo0, PPath, Parent, Module, NewPath, Status) ?- 578% named (or large) structure 579 (named_structure(Parent, Module, Defs, Arity) -> 580 get_arg(ArgNo0, Arity, ArgNo, Status), 581 arg(ArgNo, Defs, FName), 582 % path position should always be a string 583 term_string(ArgNo=FName, PosSpec), 584 append(PPath, [PosSpec], NewPath) 585 ; integer(Pos),integer(FName0), Pos = FName0 -> 586 % a large structure displayed with argument positions 587 arity(Parent, Arity), 588 get_arg(ArgNo0, Arity, ArgNo, Status), 589 term_string(ArgNo=ArgNo, PosSpec), 590 append(PPath, [PosSpec], NewPath) 591 ; 592 % not named nor large structure 593 Status = "false" 594 ). 595get_sibling_arg(Pos, ArgNo, PPath, Parent, _, NewPath, Status) :- 596 (integer(Pos) -> 597 % normal structure 598 arity(Parent, A), 599 get_arg(ArgNo, A, N1, Status), 600 term_string(N1, PosSpec), 601 append(PPath, [PosSpec], NewPath) 602 ; 603 Status = "false" 604 ). 605 606get_arg(ArgNo, A, N1, Status) :- 607 (ArgNo > A -> 608 Status = "out", 609 N1 = A 610 ;ArgNo < 1 -> 611 Status = "out", 612 N1 = 1 613 ; N1 = ArgNo, 614 Status = "true" 615 ). 616 617get_parent_path([PosS], PPath, Full, ArgNo) ?- 618 term_string(Pos, PosS), 619 valid_pos(Pos, ArgNo), !, 620 PPath = [], Pos = Full. 621get_parent_path([N|Path], [N|PPath], Pos, ArgNo) :- 622 get_parent_path(Path, PPath, Pos, ArgNo). 623 624 625move_up(N, RPath, [Status,["1"|NewPath]]) :- 626 port_remove_levels(N, RPath, RNewPath, Status), 627 reverse(RNewPath, NewPath). 628 629 630provide_subterm(Path, Depth, Term, Reply, M) :- 631 get_flag(output_mode, OM), 632 (Path == [] -> %toplevel goal 633 concat_string(["%*",OM,"w"], DF) 634 ; concat_string(["%*",OM,"Gw"], DF) 635 ), 636 get_subterm_from_path(Path, Term, Term, Sub, M), 637 open("", string, S), 638 printf(S, DF, [Depth, Sub]), 639 get_stream_info(S, name, Out), 640 close(S), 641 get_type(Sub, Type, M), 642 get_summary_info(Type, Sub, Arity, Summary), 643 Reply = [Out, Summary, Type, Arity]. 644 645 646get_type(Sub, Type, M) :- 647 type_of(Sub, Type1), 648 refine_type(Type1, Sub, M, Type). 649 650refine_type(var, Var, _, Type) :- !, 651 (meta(Var) -> Type = attributed ; Type = var). 652refine_type(compound, C, M, Type) :- !, 653 ( named_structure(C, M, _, _) -> 654 % ncompound is a structure with field names 655 Type = ncompound 656 ; C = [_|_] -> % a list (may be non-proper) 657 Type = list 658 ; 659 Type = compound 660 ). 661refine_type(goal, S, _, Type) :- !, 662 get_suspension_data(S, state, State), 663 (State == 0 -> 664 Type = suspended 665 ; State == 1 -> 666 Type = scheduled 667 ; Type = dead 668 ). 669refine_type(handle, H, _, Type) :- 670 is_expandable_handle(H, _), 671 Type = exphandle. 672refine_type(Type, _Var, _, Type). 673 674 675% check that a particular arg position is valid 676valid_pos(N0, N) :- integer(N0), !, N = N0. 677valid_pos(N0=_, N) ?- integer(N0), N = N0. %named struct (or large struct) 678%valid_pos(list(N0), N) ?- integer(N0), !, N = N0. 679%valid_pos(tail(N0), N) ?- integer(N0), !, N = N0. 680 681 682get_summary_info(Type, Term, A, Out) ?- 683 get_functorarity(Type, Term, F, A), 684 open("", string, S), 685 seek(S, end_of_file), 686 print_subterm(Type, S, F, A), 687 get_stream_info(S, name, Out), 688 close(S). 689 690 691print_subterm(attributed, S, V, _A) :- !, 692 write(S, V). 693print_subterm(var, S, V, _A) :- !, 694 write(S, V). 695print_subterm(_T, S, F, A) :- 696 writeq(S, F), 697 (A \== -1 -> % a type with valid arity 698 write(S, "/"), 699 writeq(S, A) 700 ; true 701 ). 702 703 704get_functorarity(compound, Term, F, A) ?- !, 705 functor(Term, F, A). 706get_functorarity(ncompound, Term, F, A) ?- !, 707 functor(Term, F, A). 708get_functorarity(list, _, F, A) ?- !, 709 A = 2, F = '.'. 710get_functorarity(var, Var, F, A) ?- !, 711 A = -1, F = Var. 712get_functorarity(attributed, Var, F, A) ?- !, 713 A = -1, F = Var. 714get_functorarity(atom, Atom, F, A) ?- !, 715 A = 0, F = Atom. 716get_functorarity(integer, I, F, A) ?- !, 717 A = -1, F = I. 718get_functorarity(float, J, F, A) ?- !, 719 A = -1, J = F. 720get_functorarity(breal, J, F, A) ?- !, 721 A = -1, J = F. 722get_functorarity(rational, R, F, A) ?- !, 723 A = -1, R = F. 724get_functorarity(string, S, F, A) ?- !, 725 A = -1, S = F. 726get_functorarity(handle, S, F, A) ?- !, 727 A = -1, S = F. 728get_functorarity(Susp, S, F, A) :- 729 (Susp == suspended ; Susp == scheduled ; Susp == dead), !, 730 A = -1, S = F. 731get_functorarity(_Unk, S, F, A) :- 732/* unknown type, catch it to avoid failure */ 733 A = -1, S = F. 734 735% This code should go somewhere else; but it is different from the 736% navigate subterm for the tty interface, because you can choose 737% somewhere else entirely on the tree. 738% get_subterm_from_path(+Path, +Top, +Current, -SubTerm, +Module) 739get_subterm_from_path([], Top, Current, Sub, Mod) ?- !, 740 written_term(Top, Current, Sub, Mod). 741get_subterm_from_path([PosS|Path], Top, Current, Sub, M) ?- 742 term_string(Pos, PosS), 743 (get_subterm_child(Pos, Current, Top, Child, M) -> 744 get_subterm_from_path(Path, Top, Child, Sub, M) 745 ; printf(error, "%n *** can't follow path %w in %w%n%b", [Pos,Current]) 746 ). 747 748get_subterm_child(Pos-_AttName, AVar, _, Attribute, _Module) ?- 749% attribute of an attributed var AVar. 750 integer(Pos), !, 751 get_attribute(AVar, Attribute, Pos). 752get_subterm_child(Pos=_FieldName, Current, Top, Child, Module) ?- !, 753% structure with field names 754 get_subterm_child(Pos, Current, Top, Child, Module). 755get_subterm_child(list(Pos), Current0, Top, Child, Module) ?- !, 756 written_term(Top, Current0, Current, Module), 757 list_nth(Pos, Current, Child, _). 758get_subterm_child(tail(Pos), Current0, Top, Tail, Module) ?- !, 759 Pos0 is Pos - 1, 760 written_term(Top, Current0, Current, Module), 761 list_nth(Pos0, Current, _, Tail). 762get_subterm_child(Pos, Current0, Top, Child, Module) :- 763 written_term(Top, Current0, Current, Module), 764 ( compound(Current) -> 765 functor(Current, _, A), 766 integer(Pos), 767 A >= Pos, Pos > 0, 768 arg(Pos, Current, Child) 769 ; is_handle(Current), is_expandable_handle(Current, Child) -> 770 true 771 ; is_suspension(Current) -> 772 get_suspension_data(Current, goal, Child), Pos == 1 773 ). 774 775 776is_expandable_handle(H, Exp) :- 777 get_event_handler(40, H40, M40), 778 set_event_handler(40, fail/0), 779 get_event_handler(141, H141, M141), 780 set_event_handler(141, fail/0), 781 Reset = (set_event_handler(40,H40)@M40, set_event_handler(141,H141)@M141), 782 catch( 783 ( xget(H, 0, Exp) -> 784 Reset 785 ; 786 Reset, fail 787 ), Tag, (Reset, throw(Tag)) 788 ). 789 790list_nth(1, [E0|Ls], E, Tail) ?- !, 791 E = E0, Tail = Ls. 792list_nth(N0, [_|Ls], E, Tail) :- 793 N0 > 1, 794 N1 is N0 - 1, 795 list_nth(N1, Ls, E, Tail). 796 797position_modifier(_Index-AttName, Modifier) ?- !, 798% Is an attribute 799 concat_string([AttName, ': '], Modifier). 800position_modifier(_ArgPos=FieldName, Modifier) ?- !, 801% structure with named fields 802 concat_string([FieldName, ': '], Modifier). 803position_modifier(list(N), Modifier) ?- !, 804 (N == 1 -> 805 Modifier = "[ " ; Modifier = ", " 806 ). 807position_modifier(tail(_), Modifier) ?- !, 808 Modifier = "| ". 809position_modifier(_, ""). 810 811 812inspect_get_children_for_path(SourceS, ChildCommand, PrintDepth, 813 ChildPosList, ChildInfoList) :- 814 ChildCommand = childnodes(_, _, _, PPath), 815 inspect_command(SourceS, ChildCommand, PosList), 816 ( foreach(Pos, PosList), 817 foreach(Child, ChildInfoList), 818 foreach(CPath, ChildPosList), param(SourceS, PrintDepth, PPath) do 819 ( string(Pos) -> 820 PosS = Pos 821 ; 822 term_string(Pos, PosS) 823 ), 824 append(PPath, [PosS], CPath), 825 inspect_command(SourceS, info(PrintDepth, CPath), UnmodifiedChild), 826 ( integer(Pos) -> 827 Child = UnmodifiedChild 828 ; 829 inspect_command(SourceS, modify(PosS), Modifier), 830 UnmodifiedChild = [PrintTerm, Summary, Type, Arity], 831 concat_strings(Modifier, PrintTerm, ModifiedPrintTerm), 832 concat_strings(Modifier, Summary, ModifiedSummary), 833 Child = [ModifiedPrintTerm, ModifiedSummary, Type, Arity] 834 ) 835 ). 836 837 838%---------------------------------------------------------------------- 839% Output mode setting 840%---------------------------------------------------------------------- 841 842:- mode get_tracer_output_modes(-). 843get_tracer_output_modes(Modes) :- 844 getval(dbg_goal_format_string, Format), 845 split_string(Format, "G", "%*Gw", ModeList), 846 concat_string(ModeList, Modes). 847 848:- mode set_tracer_output_modes(+). 849set_tracer_output_modes(Modes) :- 850 concat_string(["%*G",Modes,"w"], Format), 851 setval(dbg_goal_format_string, Format). 852 853 854:- mode get_tracer_print_depth(-). 855get_tracer_print_depth(Depth) :- 856 getval(dbg_print_depth, Depth). 857 858 859:- mode set_tracer_print_depth(+). 860set_tracer_print_depth(Depth) :- 861 setval(dbg_print_depth, Depth). 862 863 864%------------------------------------------------------------------- 865% Grace-like matrix display of variables 866%------------------------------------------------------------------- 867 868%:- open(queue(""), update, matrix_out_queue, [yield(on)]). 869 870/* 871commands sent by Prolog: 872% note Id should always be first arg. 873 874 setup(Id, Name, NRow, NCol, Module) 875 setup display matrix (from Module) with Name and Id, of size NRowxNCol 876 877 displ(Id, Row, Col, String, TermState, BackorForward) 878 String is the printed representation of Term at matrix Id at Row,Col. 879 TermState is the status of the term (for break-points), BackorForward 880 is if this value is from backtracking or forward execution 881 882 kill(Id) 883 Kill the display matrix Id 884 885 interact(Id) 886 interact with user at display matrix Id 887 888Id is used to identify a matrix rather than Name because it is not certain that 889a matrix window will dissapear beyond its `logical scope'. Id is monotonically 890increasing number assigned by the system that ensure each new matrix has a 891unique number 892 893Need to keep two variable containers: 894 895matdisplayid: the current value of the id. This is incremented whenever 896 a new matrix is created. Is a variable. 897 898matdisplaydata: this keeps the actual information associated with all the 899 matricies. Is a reference. 900*/ 901 902:- local struct(matrix(id,name,module,matrix,suspl)). 903 904convert_list_to_matrix(List, 0, Matrix) :- !, 905 Matrix =.. [[]|List]. 906convert_list_to_matrix(List, N, Matrix) :- 907 integer(N), N > 0, !, 908 length(List, L), 909 (N >= L -> 910 Matrix =.. [[]|List] 911 ; divide_list(N, List, LLists, unused, 1, M), 912 dim(Matrix, [M,N]), 913 (foreach(L, LLists), foreacharg(Row, Matrix) do 914 Row =.. [[]|L] 915 ) 916 ). 917 918divide_list(N, List0, LLists0, Fill, M0, M) :- 919 make_one_sublist(N, List0, List1, Sub, Fill), 920 (List1 == [] -> 921 LLists0 = [Sub], 922 M0 = M 923 ; 924 LLists0 = [Sub|LLists1], 925 M1 is M0 + 1, 926 divide_list(N, List1, LLists1, Fill, M1, M) 927 ). 928 929make_one_sublist(I, [], List1, Sub, Fill) ?- !, 930 List1 = [], 931 (foreach(E, Sub), count(_, 1, I), param(Fill) do 932 E = Fill 933 ). 934make_one_sublist(0, List0, List1, Sub, _) ?- !, List1 = List0, Sub = []. 935make_one_sublist(I0, List0, List, Sub0, Fill) ?- 936 List0 = [E|List1], Sub0 = [E|Sub1], 937 I1 is I0 - 1, 938 make_one_sublist(I1, List1, List, Sub1, Fill). 939 940 941make_display_matrix_body(Matrix, Name, Module) :- 942 make_display_matrix_body(Matrix, 1, any, constrained, Name, Module). 943 944 945/* make_display_matrix_body(+Matrix, +Prio, +Type, +SList, +Name) 946 creates a term display matrix. Matrix is either a list or a matrix of 947 terms. Prio is the priority the demon would be suspended at, Type is 948 what type of information would be displayed, SList is the suspension 949 list the demon's suspension would be added to, and Name is the name 950 used for this display matrix 951*/ 952make_display_matrix_body(List/NRow, Prio, Type, SList, Name0, Module) ?- !, 953 convert_list_to_matrix(List, NRow, Matrix), 954 make_display_matrix_body(Matrix, Prio, Type, SList, Name0, Module). 955make_display_matrix_body(List, Prio, Type, SList, Name0, Module) :- 956 List = [_|_], !, % is a list 957 convert_list_to_matrix(List, 0, Matrix), 958 make_display_matrix_body(Matrix, Prio, Type, SList, Name0, Module). 959make_display_matrix_body(Matrix, Prio, Type, SList, Name, Module) :- 960 compound(Matrix), \+(Matrix = _/_), 961 display_matrix_dim(Matrix, 2, Dims), 962 add_matname(Name, Matrix, Module, Id, SL, Module), 963 (set_up_matdisplay(Dims, Matrix, Prio, Type, SList, Name, Id, SL, Module) -> 964 true ; sepia_kernel:set_bip_error(5) 965 ), 966 % kill window on backtracking 967 !, (true ; kill_matdisplay(Name,Module,_), fail). 968make_display_matrix_body(Matrix, Prio, Type, SList, Name, Module) :- 969 sepia_kernel:get_bip_error(Error), 970 (Error == 5 -> kill_matdisplay(Name,Module,_) ; true), 971 error(Error, make_display_matrix(Matrix, Prio, Type, SList, Name), Module). 972 973/* display_matrix_dim(+Matrix, +MaxDepth, -Dim) 974 returns the dimensions of a display matrix Matrix. MaxDepth is the max. 975 number of dimensions that a matrix will be decomposed to for a 976 display_matrix (cannot be more than 2 as display matrix must be 2d or less) 977*/ 978display_matrix_dim(_Matrix, 0, Dim) :- !, Dim = []. 979display_matrix_dim(Matrix, N, [D|Ds]) :- 980 compound(Matrix), 981 functor(Matrix, [], D), 982 N1 is N - 1, 983 (foreacharg(Row, Matrix), param([Ds,N1]) do 984 display_matrix_dim(Row,N1, Ds) 985 ), !. 986display_matrix_dim(_Matrix, _, []). 987 988gen_mat_name(Name0, Module, FName) :- 989 (atomic(Name0) -> 990 concat_string([Name0], NameS), 991 FName = NameS@Module 992 ; sepia_kernel:set_bip_error(5) 993 ). 994 995set_up_matdisplay([N], Matrix, Prio, Type, SList, Name, Id, SL, Module) ?- !, 996 init_matdisplay(1, N, Name, Id, Module), 997 set_up_matrowdis(1, N, Matrix, Prio, Type, SList, Id, SL, []), 998 matdisplay_interact(Id). 999set_up_matdisplay([M,N], Matrix, Prio, Type, SList, Name, Id, SL, Module) ?- 1000 init_matdisplay(M, N, Name, Id, Module), 1001 (foreacharg(Row, Matrix), param(N,Prio,Type,SList,Id), count(I, 1, M), 1002 fromto(SL, S0, S1, []) do 1003 set_up_matrowdis(I, N, Row, Prio, Type, SList, Id, S0, S1) 1004 ), matdisplay_interact(Id). 1005 1006set_up_matrowdis(CurrentRow, ColSize, Row, Prio, Type, SList, Id, SLIn, SLOut) :- 1007 (foreacharg(E, Row), count(I, 1, ColSize), fromto(SLIn, SL0, SL1, SLOut), 1008 param(CurrentRow,Prio,Type,Id,SList) do 1009 set_up_mattermdis(E, CurrentRow, I, Prio, Type, SList, Id, SL0, SL1) 1010 ). 1011 1012 1013set_up_mattermdis(E, Row, Col, Prio, Type, SList, Id, [Susp|Out], Out) :- 1014 (nonground(E) -> 1015 get_display_string(E, Type, String, _), 1016 suspend(term_display_demon(E,Row,Col,Id,Type,String, Susp), Prio, E->SList, Susp), 1017 Type1 = Type 1018 ; Type1 = none 1019 ), 1020 send_display_elm(E, Row, Col, Id, Type1, _). 1021 1022matdisplay_interact(Id) :- 1023 write_exdr(matrix_out_queue, interact(Id)), 1024 flush(matrix_out_queue). 1025 1026 1027:- demon term_display_demon/7. 1028:- set_flag(term_display_demon/7, leash, notrace). 1029:- set_flag(term_display_demon/7, skip, on). 1030 1031term_display_demon(Term, Row, Col, Id, Type, _Old, Susp) :- 1032 send_display_elm(Term, Row, Col, Id, Type, String), 1033 (nonground(Term) -> 1034 get_suspension_data(Susp, goal, Goal), 1035 setarg(6, Goal, String) 1036 ; kill_suspension(Susp) 1037 ). 1038term_display_demon(Term, Row, Col, Id, _Type, Old, _Susp) :- 1039 (nonground(Term) -> G = nonground ; G = wasground), 1040 send_display_string(Id, Row, Col, Old, G, back), 1041 fail. 1042 1043 1044init_matdisplay(NRow, NCol, Name, Id, Module) :- 1045 write_exdr(matrix_out_queue, setup(Id, Name, NRow, NCol, Module)), 1046 flush(matrix_out_queue). 1047 1048kill_matdisplay(Name, Module, Cond) :- 1049 (shutdown_mat(Name, Id, Module) -> 1050 Cond = yes, 1051 write_exdr(matrix_out_queue, kill(Id)), 1052 flush(matrix_out_queue) 1053 ; Cond = no 1054 ). 1055 1056send_display_elm(E, Row, Col, Id, Type, String) :- 1057 get_display_string(E, Type, String, TState), 1058 send_display_string(Id, Row, Col, String, TState, forward). 1059 1060send_display_string(Id, Row, Col, String, G, State) :- 1061 write_exdr(matrix_out_queue, disp(Id, Row, Col, String, G, State)), 1062 flush(matrix_out_queue). 1063 1064add_matname(Name0,Matrix,Module,Id,SL, Module) :- 1065 getval(matdisplaydata, Mats), 1066 getval(matdisplayid, Id0), 1067 concat_string([Name0], Name), % make sure it is a string 1068 NewMat = matrix{name:Name,module:Module}, 1069 (\+member(NewMat, Mats) -> % \+member because 0 terminates list 1070 Id is Id0 + 1, 1071 setval(matdisplayid, Id), 1072 concat_string([Name0], Name), % make sure it is a string 1073 NewMat = matrix{id:Id,matrix:Matrix,suspl:SL}, 1074 setval(matdisplaydata, [NewMat|Mats]) 1075 ; sepia_kernel:set_bip_error(6) 1076 ). 1077 1078shutdown_mat(Name0, Id, Module) :- 1079 getval(matdisplaydata, Mats), 1080 concat_string([Name0], Name), 1081 M = matrix{id:Id,name:Name,module:Module,suspl:Ss}, 1082 memberchk(M, Mats), 1083 % stop sending of information to GUI side 1084 (foreach(S,Ss) do kill_suspension(S)). 1085 1086get_matrix_term(Id, R, C, Term, Mod) :- 1087 getval(matdisplaydata, Ms), 1088 member(matrix{id:Id,module:Mod,matrix:Mat}, Ms), 1089 dim(Mat, Bounds), 1090 get_subscripts(Bounds, R, C, Sub), 1091 subscript(Mat, Sub, Term). 1092 1093get_subscripts([N], R, C0, [C]) :- !, 1094 (R == 1, N >= C0 -> C = C0 ; 1095 writeln(error, "Matrix subscript error"), 1096 C = N 1097 ). 1098get_subscripts([N,M], R0, C0, [R,C]) :- !, 1099 (N >= R0 -> R = R0 1100 ; writeln(error, "Matrix subscript error"), 1101 R = N 1102 ), 1103 (M >= C0 -> C = C0 1104 ; writeln(error, "Matrix subscript error"), 1105 C = M 1106 ). 1107get_subscripts(_, _R, _C, []) :- 1108 writeln(error, "Matrix subscript error"). 1109 1110 1111kill_display_matrix_body(Name@Module, _) ?- !, % for compatibility only 1112 kill_display_matrix_body(Name, Module). 1113kill_display_matrix_body(Name, Module) :- 1114 kill_matdisplay(Name, Module, Cond), 1115 (Cond == yes -> ! ; sepia_kernel:set_bip_error(6)). 1116kill_display_matrix_body(Name, Module) :- 1117 sepia_kernel:get_bip_error(Error), 1118 error(Error, kill_display_matrix(Name), Module). 1119 1120get_display_string(E, _Type, String, G) :- 1121 (nonground(E) -> G = nonground ; G = ground), 1122 open("", string, S), 1123 printf(S, "%mQPw", [E]), 1124 get_stream_info(S, name, String), 1125 close(S). 1126 1127 1128%--------------------------------------------------------------------- 1129% Observed terms 1130%--------------------------------------------------------------------- 1131 1132create_observed([], _) :- !. 1133create_observed(Os, trace_line{frame:tf{module:Module}}) :- 1134 make_observed_list(Os, OL), 1135 getval(observed_count, Count), 1136 incval(observed_count), 1137 concat_atom(['Observing#', Count], Label), 1138 make_display_matrix(OL/2, Label)@Module. 1139 1140make_observed_list([], Out) :- !, Out = []. 1141make_observed_list([o(Source,Path,Label)|Os], Out) :- 1142 get_inspected_term(Source, Term, Module), 1143 get_subterm_from_path(Path, Term, Term, Sub, Module), 1144 Out = [Label,Sub|Out1], 1145 make_observed_list(Os, Out1). 1146 1147%---------------------------------------------------------------------- 1148% Library browser 1149%---------------------------------------------------------------------- 1150 1151init_library_info :- 1152% collect the available libraries with valid info files 1153 collect_library_info(Info), 1154 setval(library_info, Info). 1155 1156collect_library_info(Info) :- 1157 get_flag(library_path, LibPaths), 1158 (foreach(LP, LibPaths), fromto(UnsortedInfo, InfoIn, InfoOut, []) do 1159 get_flag(eclipse_info_suffix, ISuf), 1160 concat_string(["*", ISuf], IFilter), 1161 read_directory(LP, IFilter, _, Fs0), 1162 (foreach(File, Fs0), fromto(InfoIn, Info1, Info2, InfoOut), 1163 param(LP) do 1164 (get_module_from_infofile(LP, File, MFInfo) -> 1165 Info1 = [MFInfo|Info2] ; Info1 = Info2 1166 ) 1167 ) 1168 ), 1169 sort(module of mfile, <, UnsortedInfo, Info). 1170 1171get_module_from_infofile(Path, File, MFile) :- 1172 concat_string([Path, "/", File], FullName), 1173 get_file_info(FullName, readable, on), 1174 open(FullName, read, In), 1175 (read(In, :-module(Module)) -> % module should be first item in file 1176 MFile = mfile{dir:Path,module:Module,file:FullName}, 1177 close(In) 1178 ; close(In), fail 1179 ). 1180 1181% assumes File is readable and is a valid information file 1182read_interface_file(File, ILines, CLines) :- 1183 open(File, read, In), 1184 read_interface_file1(In, ILines, CLines), 1185 close(In). 1186 1187read_interface_file1(In, ILines0, CLines0) :- 1188 (at_eof(In) -> 1189 ILines0 = [], CLines0 = [] 1190 ; (read(In, :-Line) -> % all info in interface file should be directives 1191 filter_interface_line(Line, ILines0, ILines1, CLines0, CLines1) 1192 ; 1193 % ignore invalid lines 1194 ILines1 = ILines0, 1195 CLines1 = CLines0 1196 ), 1197 read_interface_file1(In, ILines1, CLines1) 1198 ). 1199 1200filter_interface_line(module(_), ILines0, ILines, CLines0, CLines) ?- !, 1201 CLines0 = CLines, 1202 ILines0 = ILines. 1203filter_interface_line(comment(T,C), ILines0, ILines, CLines0, CLines) ?- !, 1204 CLines0 = [comment(T,C)|CLines], 1205 ILines0 = ILines. 1206filter_interface_line(Line, ILines0, ILines, CLines, CLines) :- 1207 ILines0 = [Line|ILines]. 1208 1209 1210% find the exported predicates, sort them into Preds, and place other info 1211% items into Others in the order they occur in the interface file 1212sort_minfo(MInfo, Preds, Others) :- 1213 (foreach(Item, MInfo), fromto(Preds0, P0,P1, []), 1214 fromto(Others, O0, O1, []) do 1215 (Item = export(Name/Arity) -> 1216 P0 = [Name/Arity|P1], O0 = O1 1217 ; P0 = P1, O0 = [Item|O1] 1218 ) 1219 ), 1220 sort(Preds0, Preds). 1221 1222% support for returning the children and node content for libbrowser widget 1223 1224extract_lbpath_info(["top"|RestPath], PInfo, Deepest) :- 1225 getval(lbpath_type, [top|PTypes]), 1226 lbindex_info(RestPath, PTypes, top, PInfo, Deepest). 1227 1228lbindex_info([], _PTypes, ParentType, PInfo, Deepest) :- 1229 Deepest = ParentType, PInfo = []. 1230lbindex_info([P|Ps], [Type|Types], _, [PInfo|PInfo0], Deepest) :- 1231 get_onelbindex_info(Type, P, PInfo, ActualType), 1232 lbindex_info(Ps, Types, ActualType, PInfo0, Deepest). 1233 1234get_onelbindex_info(dir, Dir, PInfo, ActualType) ?- 1235 ActualType = dir, 1236 PInfo = dir:Dir. 1237get_onelbindex_info(module, SModule, PInfo, ActualType) ?- 1238 atom_string(Module, SModule), % SModule is a string 1239 is_lbmodule(Module), 1240 ActualType = module, 1241 PInfo = module:Module. 1242get_onelbindex_info(interface, IntPath, PInfo, ActualType) ?- 1243 term_string(Item, IntPath), 1244 (Item = Name/Arity -> 1245 PInfo = interface:Name/Arity, 1246 ActualType = interface(predicate) 1247 ; PInfo = interface:Item, 1248 ActualType = interface(nonpredicate) 1249 ). 1250 1251expand_lbnode(Path, Children) :- 1252 extract_lbpath_info(Path, PInfo, Deepest), 1253 return_lbnode_children(Deepest, PInfo, Children). 1254 1255lbnode_display(Path, DText, Highlight) :- 1256 extract_lbpath_info(Path, PInfo, Deepest), 1257 (Deepest = module -> 1258 memberchk(module:M, PInfo), 1259 (get_flag(loaded_library, M) -> 1260 Highlight = current ; Highlight = highlight 1261 ) 1262 ; 1263 Highlight = none 1264 ), 1265 return_lbnode_text(Deepest, PInfo, DText). 1266 1267lbnode_info(Path, IsOpen, NodeInfo, Module) :- 1268 extract_lbpath_info(Path, PInfo, Deepest), 1269 return_lbnode_info(Deepest, PInfo, IsOpen, NodeInfo, Module). 1270 1271 1272% load the module Lib 1273lbnode_loadmodule(Lib) :- 1274 get_flag(toplevel_module,Top), 1275 lib(Lib)@Top. 1276 1277% predicates to return information on items 1278 1279return_html_root(Root) :- 1280 get_flag(installation_directory, ECDir), 1281 concat_string([ECDir, "/doc/index.html"], RootInternal), 1282 os_file_name(RootInternal, Root). 1283 1284return_lbnode_children(top, _, Dirs) ?- 1285 return_libdirs(Dirs). 1286return_lbnode_children(dir, PInfo, Modules) ?- 1287 memberchk(dir:Dir, PInfo), 1288 return_modules_in_dir(Dir, Modules). 1289return_lbnode_children(module, PInfo, InterNodes) ?- 1290 memberchk(module:Module, PInfo), 1291 memberchk(dir:Dir, PInfo), 1292 return_module_info(Module, Dir, minfo{interface:Interface}), 1293 sort_minfo(Interface, Preds, Others), 1294 (foreach(P, Preds), fromto(InterNodes, Nodes0, Nodes1, InterNodes1) do 1295 term_string(P, PIndex), 1296 Nodes0 = [PIndex|Nodes1] 1297 ), 1298 (foreach(O, Others), fromto(InterNodes1, Nodes0, Nodes1, []) do 1299 term_string(O, OIndex), 1300 Nodes0 = [OIndex|Nodes1] 1301 ). 1302return_lbnode_children(interface(predicate), _PInfo, Expanded) ?- !, 1303 % cannot expand predicates yet 1304 Expanded = []. 1305return_lbnode_children(interface(nonpredicate), _PInfo, Expanded) ?- 1306 Expanded = []. 1307 1308 1309return_lbnode_text(top, _, DText) ?- DText = "libraries". 1310return_lbnode_text(dir, PInfo, DText) ?- 1311 DText = Dir, 1312 memberchk(dir:Dir, PInfo). 1313return_lbnode_text(module, PInfo, DText) ?- 1314 memberchk(module:M, PInfo), 1315 memberchk(dir:Dir, PInfo), 1316 (return_module_summary(M, Dir, Summary) -> 1317 concat_string([M, " \n ", Summary], DText) 1318 ; atom_string(M, DText) 1319 ). 1320return_lbnode_text(interface(predicate), PInfo, DText) ?- !, 1321 memberchk(interface:Name/Arity, PInfo), 1322 memberchk(dir:Dir, PInfo), 1323 memberchk(module:M, PInfo), 1324 construct_pred_display(Name, Arity, M, Dir, DText). 1325return_lbnode_text(interface(nonpredicate), PInfo, DText) ?- 1326 memberchk(interface:Item, PInfo), 1327 term_string(Item, DText). 1328 1329construct_pred_display(Name, Arity, M, Dir, DText) :- 1330 return_pred_comment(M, Dir, Name, Arity, PredCom), 1331 (PredCom \== [] -> 1332 construct_pred_display_from_comments(Name, Arity, PredCom, DText) 1333 ; term_string(Name/Arity, DText) % no comment info for pred 1334 ). 1335 1336construct_pred_display_from_comments(Name, Arity, PComs, DText) :- 1337 get_pred_summary(PComs, Summary), 1338 construct_pred_template(Name, Arity, PComs, Template), 1339 concat_string([Template, "\n ", Summary], DText). 1340 1341get_pred_summary(PComs, Sum) :- 1342 (memberchk(summary:Sum, PComs) ; Sum = ""), !. 1343 1344construct_pred_template(Name, Arity, PComs, Template) :- 1345 (memberchk(template:Template,PComs) -> 1346 true 1347 ; 1348 return_pred_modes(Name, Arity, PComs, Modes), 1349 generalise_modes(Modes, Mode), 1350 construct_onepred_template(Name, Arity, PComs, Mode, Template) 1351 ). 1352 1353construct_onepred_template(Name, Arity, PComs, Mode, DText) :- 1354 ((memberchk(args:ArgDs, PComs), length(ArgDs, Arity)) -> 1355 (foreach(ArgDesc, ArgDs), foreach(Name, ANames) do 1356 ((ArgDesc = Name0:_, string(Name0)) -> 1357 Name = Name0 ; Name = "" 1358 ) 1359 ) 1360 ; 1361 (count(_,1,Arity), foreach("", ANames) do true) 1362 ), 1363 (foreach(AName, ANames), foreacharg(AMode, Mode), foreach(Arg, ArgsString) do 1364 concat_string([AMode,AName], Arg) 1365 ), 1366 construct_pred_template_with_args(Name, Arity, ArgsString, DText). 1367 1368 1369construct_pred_template_with_args(Name, _, Args, DText) :- 1370 (Args == [] -> 1371 concat_string([Name], DText) 1372 ; 1373 DTextList = [Name, "("|ArgList], 1374 construct_arglist(Args, ArgList), 1375 concat_string(DTextList, DText) 1376 ). 1377 1378construct_arglist([Last], Out) ?- !, 1379 Out = [Last, ")"]. 1380construct_arglist([Arg|Args], Out) ?- 1381 Out = [Arg, ", "|Out0], 1382 construct_arglist(Args, Out0). 1383 1384return_pred_modes(Name, Arity, PComs, Modes) :- 1385 findall(Mode, (member(amode:Mode, PComs), functor(Mode, Name, Arity)), 1386 Modes0), 1387 (Modes0 == [] -> 1388 % no modes found, generate an all '?' mode. 1389 functor(GenMode, Name, Arity), 1390 (foreacharg(?,GenMode) do true), 1391 Modes = [GenMode] 1392 ; Modes0 = Modes 1393 ). 1394 1395return_lbnode_info(top, _, IsOpen, NInfo, M) ?- 1396 M = "", 1397 (IsOpen == 1 -> 1398 NInfo = [[normal,"ECLiPSe libraries"]] ; NInfo = [] 1399 ). 1400return_lbnode_info(dir, _PInfo, IsOpen, NInfo, M) ?- 1401 % could add info on purpose of each directory 1402 M = "", 1403 (IsOpen == 1 -> 1404 NInfo = [[normal,"An ECLiPSe library directory"]] ; NInfo = [] 1405 ). 1406return_lbnode_info(module, PInfo, IsOpen, NInfo, M) ?- 1407 memberchk(module:M, PInfo), 1408 (IsOpen == 1 -> 1409 memberchk(dir:Dir, PInfo), 1410 return_module_desc(M, Dir, MDesc0), 1411 ( string(MDesc0) -> 1412 NInfo = [[normal, MDesc0]] 1413 ; MDesc0 = ascii(MDesc) -> 1414 NInfo = [[normal, MDesc]] 1415 ; NInfo = [] % don't try to cope with non-plain ascii formats 1416 ) 1417 ; 1418 NInfo = [] 1419 ). 1420return_lbnode_info(interface(predicate), PInfo, _IsOpen, NInfo, M) ?- !, 1421 memberchk(dir:_Dir, PInfo), 1422 memberchk(module:M, PInfo), 1423 memberchk(interface:Name/Arity, PInfo), 1424 return_pred_info(M, Name, Arity, NInfo). 1425return_lbnode_info(interface(nonpredicate), PInfo, _IsOpen, NInfo, M) ?- 1426 memberchk(module:M, PInfo), 1427 NInfo = []. 1428 1429 1430generalise_modes([Mode|Modes], GenM) :- 1431 generalise_modes(Modes, Mode, GenM). 1432 1433generalise_modes([], Gen, Gen). 1434generalise_modes([Mode1|Modes], Mode2, Gen) :- 1435 functor(Mode1, Name, Arity), 1436 functor(GenMode1, Name, Arity), 1437 (foreacharg(M1, Mode1), foreacharg(M2, Mode2), foreacharg(G, GenMode1) do 1438 lub(M1, M2, G) 1439 ), 1440 generalise_modes(Modes, GenMode1, Gen). 1441 1442% lub(PX, PY, PLub) 1443% 1444% least upper bound of 2 modes (cf. lattice above) 1445 1446lub(-, Y, LUB) :- 'lub-'(Y, LUB). 1447lub(++, Y, LUB) :- 'lub++'(Y, LUB). 1448lub(+-, Y, LUB) :- 'lub+-'(Y, LUB). 1449lub(-+, Y, LUB) :- 'lub-+'(Y, LUB). 1450lub(+, Y, LUB) :- 'lub+'(Y, LUB). 1451lub(?, _, ?). 1452 1453'lub-'(-, -). 1454'lub-'(++, -+). 1455'lub-'(+-, -+). 1456'lub-'(-+, -+). 1457'lub-'(+, ?). 1458'lub-'(?, ?). 1459 1460'lub+'(-, ?). 1461'lub+'(++, +). 1462'lub+'(+-, +). 1463'lub+'(-+, ?). 1464'lub+'(+, +). 1465'lub+'(?, ?). 1466 1467'lub++'(-, -+). 1468'lub++'(++, ++). 1469'lub++'(+-, +-). 1470'lub++'(-+, -+). 1471'lub++'(+, +). 1472'lub++'(?, ?). 1473 1474'lub+-'(-, -+). 1475'lub+-'(++, +-). 1476'lub+-'(+-, +-). 1477'lub+-'(-+, -+). 1478'lub+-'(+, +). 1479'lub+-'(?, ?). 1480 1481'lub-+'(-, -+). 1482'lub-+'(++, -+). 1483'lub-+'(+-, -+). 1484'lub-+'(-+, -+). 1485'lub-+'(+, ?). 1486'lub-+'(?, ?). 1487 1488 1489return_module_info(Module, Dir, MInfo) :- 1490 getval(library_info, Info), 1491 memberchk(mfile{module:Module,dir:Dir, file:File}, Info), 1492 read_interface_file(File, InterItems, Comments), 1493 MInfo = minfo{interface:InterItems, comments:Comments}. 1494 1495return_module_summary(Module, Dir, Summary) :- 1496 return_module_info(Module, Dir, minfo{comments:MCom}), 1497 memberchk(comment(summary, Summary), MCom). 1498 1499return_module_desc(Module, Dir, Desc) :- 1500 return_module_info(Module, Dir, minfo{comments:MCom}), 1501 (memberchk(comment(desc, Desc), MCom) -> 1502 true ; Desc = "" 1503 ). 1504 1505return_modules_in_dir(Directory, Modules) :- 1506 getval(library_info, Info), 1507 findall(M, member(mfile{dir:Directory,module:M}, Info), Modules). 1508 1509return_libdirs(Dirs) :- 1510 get_flag(library_path, Dirs). 1511 1512return_pred_comment(M, Dir, Name, Arity, PCom) :- 1513 return_module_info(M, Dir, minfo{comments:MCom}), 1514 (memberchk(comment(Name/Arity, PCom), MCom) -> 1515 true ; PCom = [] 1516 ). 1517 1518return_pred_info(M, Name, Arity, PredInfo) :- 1519% just return what help would return 1520 term_string(M:Name/Arity, PredSpecS), 1521 gui_help_string(PredSpecS, Info), 1522 PredInfo = [[normal, Info]]. 1523 1524construct_args_descr(PredCom, PredInfoIn, PredInfoOut) :- 1525 (memberchk(args:Args, PredCom) -> 1526 length(Args, N), 1527 (N > 0 -> 1528 open("", string, ArgsDesc), 1529 (foreach(Name:Desc, Args), param(ArgsDesc) do 1530 printf(ArgsDesc, "%-20s %s\n", [Name,Desc]) 1531 ), 1532 get_stream_info(ArgsDesc, name, ArgsString), 1533 close(ArgsDesc), 1534 PredInfoIn = [[heading, "Arguments"], 1535 [normal, ArgsString],[normal,""]|PredInfoOut] 1536 ; 1537 PredInfoIn = PredInfoOut 1538 ) 1539 ; 1540 PredInfoIn = PredInfoOut 1541 ). 1542 1543% type checks 1544is_lbmodule(Module) :- 1545 atom(Module), 1546 getval(library_info, Info), 1547 memberchk(mfile{module:Module}, Info). 1548 1549 1550%---------------------------------------------------------------------- 1551% Handlers for various GUI requests 1552% Most are called from the GUI via RPCs 1553%---------------------------------------------------------------------- 1554 1555:- local record(new_source_files). 1556 1557:- open(queue(""), update, gui_dg_buffer). 1558%:- open(queue(""), update, gui_dg_info, [yield(on)]). creation done in gui 1559 1560compile_os_file(OsFile, Module) :- 1561 os_file_name(File, OsFile), 1562 catchall(compile(File, Module)), 1563 % flush here, because the flushes in the nested emulator 1564 % within the compiler are ignored... 1565 flush(warning_output), 1566 flush(error), 1567 flush(output). 1568 1569 1570use_module_os(OsFile, Module) :- 1571 os_file_name(File, OsFile), 1572 catchall(use_module(File)@Module), 1573 % flush here, because the flushes in the nested emulator 1574 % within the compiler are ignored... 1575 flush(warning_output), 1576 flush(error), 1577 flush(output). 1578 1579catchall(Goal) :- 1580 catch(Goal, Tag, top_abort(Tag)). 1581 1582top_abort(abort) ?- !. 1583top_abort(Tag) :- 1584 stack_overflow_message(Tag), !, 1585 top_abort(abort). 1586top_abort(Tag) :- 1587 catch(error(230, throw(Tag)), T, true), 1588 top_abort(T). 1589 1590list_predicates(Which, Module, AuxFilter, Sorted) :- 1591 ( Which = exported -> 1592 Goal = (current_module_predicate(exported_reexported,P)@Module) 1593 ; Which = local -> 1594 Goal = (current_module_predicate(local,P)@Module) 1595 ; Which = defined -> 1596 Goal = (current_module_predicate(defined,P)@Module) 1597 ; Which = visible -> 1598 Goal = (current_predicate(P)@Module;current_built_in(P)@Module) 1599 ; Which = imported -> 1600 Goal = ( 1601 (current_predicate(P)@Module;current_built_in(P)@Module), 1602 get_flag(P,visibility,V)@Module, 1603 memberchk(V,[imported,reexported]) 1604 ) 1605 ; 1606 Goal = fail 1607 ), 1608 findall(PS, 1609 ( 1610 not is_locked(Module), 1611 Goal, 1612 filter_auxiliary(AuxFilter, P, Module), 1613 term_string(P,PS)@Module 1614 ), 1615 Preds), 1616 sort(0, =<, Preds, Sorted), 1617 true. 1618 1619 filter_auxiliary(1, P, Module) :- get_flag(P,auxiliary,off)@Module. 1620 filter_auxiliary(0, _, _). 1621 1622flag_value(PredS,Name,M,String) :- 1623 % this can be called with an empty selection from Tcl... 1624 PredS \== "", 1625 term_string(Pred, PredS), 1626 get_flag(Pred, Name, Value)@M, 1627 term_string(Value, String). 1628 1629set_flag_string(PredS,Name,Value,M) :- 1630 term_string(Pred, PredS), 1631 set_flag(Pred, Name, Value)@M. 1632 1633record_source_file(XFile) :- 1634 os_file_name(File1, XFile), 1635 canonical_path_name(File1, File2), 1636 atom_string(File3, File2), 1637 ( recorded(new_source_files, File3) -> true 1638 ; record(new_source_files, File3) ). 1639 1640get_source_info(PredS, M, OSFile, Offset) :- 1641 term_string(N/A, PredS), 1642 atom(N), 1643 integer(A), 1644 current_module(M), % may fail 1645 % source_line and source_offset are for end of last predicate 1646 get_flag(N/A, source_file, File)@M, 1647 get_flag(N/A, source_offset, Offset)@M, 1648 os_file_name(File, OSFile). 1649 1650 1651% list_files/1 returns a list of lists of strings of the form 1652% ["filename", "status", "module"] where the filename is in the 1653% syntax of the operating system 1654 1655list_files(Files) :- 1656 findall([F,S,M], source_file_status(F,S,M), Files). 1657 1658 source_file_status(XFile, State, SModule) :- 1659 current_compiled_file(File,CompileTime,Module), 1660 ( erase(new_source_files, File),fail ; true ), 1661 ( get_file_info(File,mtime) =:= CompileTime -> 1662 State = "ok" 1663 ; get_file_info(File,mtime,_) -> 1664 State = "modified" 1665 ; 1666 State = "nonexisting" 1667 ), 1668 atom_string(Module, SModule), 1669 atom_string(File, SFile), 1670 os_file_name(SFile, XFile). 1671 source_file_status(XFile, "new", "") :- 1672 recorded(new_source_files, File), 1673 atom_string(File, SFile), 1674 os_file_name(SFile, XFile). 1675 1676 1677list_modules(Modules, ToplevelModule) :- 1678 findall(Module, current_module(Module), Modules), 1679 get_flag(toplevel_module, ToplevelModule). 1680 1681% gui_help(+Stream, +Subject) 1682% prints help on the string Subject onto Stream 1683 1684gui_help(Stream,SubjectString) :- 1685 get_stream(output, S), 1686 set_stream(output, Stream), 1687 ( catch(gui_help1(SubjectString), _, fail) -> 1688 true 1689 ; 1690 printf("No help available on \"%s\"%n", SubjectString) 1691 ), 1692 set_stream(output, S), 1693 flush(Stream). 1694 1695 gui_help1(SubjectString) :- 1696 term_string(Subject,SubjectString), % for name/arity terms 1697 ( var(Subject) -> 1698 help(SubjectString) % for upper case words 1699 ; 1700 help(Subject) 1701 ). 1702 1703% returns the help info as a string (Info), given the pred. spec. as a string 1704gui_help_string(PredSpecS, Info) :- 1705 open(string(""), write, s), 1706 gui_help(s, PredSpecS), 1707 get_stream_info(s, name, Info), 1708 close(s). 1709 1710 1711% gui_dg(+Which,+Trigger,+Filter) 1712% send delayed goals to gui, filtering out goals according to filter 1713% Which specifies if the goals should be obtained from the global 1714% list (0), or from the symbolic trigger Trigger (1) 1715% currently Filter is: dg_filter(tracedonly, spiedonly,scheduledonly) 1716% tracedonly: only send traced goals 1717% speidonly: only send spied goals 1718% scheduledonly: only send scheduled goals 1719 1720gui_dg(Which, Trigger, Filter) :- 1721 get_suspensions(Which, Trigger, Susps), 1722 ( foreach(Susp, Susps), param(Filter) do 1723 ( suspension_info(Susp,Filter) -> true ; true ), 1724 % flush before the queue buffers get too large... 1725 ( at(gui_dg_info) > 32000 -> 1726 write_exdr(gui_dg_info, end), 1727 flush(gui_dg_info) 1728 ; true ) 1729 ), 1730 write_exdr(gui_dg_info, end), 1731 flush(gui_dg_info). 1732 1733 get_suspensions(0, _, Susps) :- % all suspensions 1734 suspensions(Susps). 1735 get_suspensions(1, Trigger, Susps) :- 1736 ( is_list(Trigger) -> 1737 ( foreach(T, Trigger), fromto(Susps, ThisNext, Next, []) 1738 do 1739 attached_suspensions(T, This), 1740 append(This, Next, ThisNext) 1741 ) 1742 ; 1743 attached_suspensions(Trigger, Susps) 1744 ). 1745 1746 suspension_info(S, Filter) :- 1747 get_suspension_data(S, goal, Goal), 1748 get_suspension_data(S, module, M), 1749 get_suspension_data(S, invoc, Invoc), 1750 get_suspension_data(S, priority, Prio), 1751 get_suspension_data(S, state, State), 1752 ( get_suspension_data(S, spy, on) -> Spied = 0'+ ; Spied = 0' ), 1753 functor(Goal, F, A), 1754 filter_dg(F/A, Filter, dg_filter{spiedonly:Spied,wakeonly:State}), 1755 printf(gui_dg_buffer, "%n %c(%d) <%d> ", [Spied, Invoc, Prio]), 1756 % delay goals are printed with format and depth options of tracer 1757 getval(dbg_goal_format_string, Format), 1758 getval(dbg_print_depth, PDepth), 1759 printf(gui_dg_buffer, Format, [PDepth,Goal])@M, 1760 read_string(gui_dg_buffer, end_of_file, LineLength, DGString), 1761 write_exdr(gui_dg_info, info(State,Prio,Invoc,LineLength,DGString)). 1762 1763 % filter_dg fails if the Suspended goal is not to be sent to the gui side 1764 % filter_dg(+PredSpec, +FilterSettings, +FilterValues) 1765 % FilterSettings is the settings for the various filters from the gui 1766 % and FilterValues is any value of the delay goal that may be relevant in 1767 % determining if a particular filter should be applied. Both are in the 1768 % dg_filter structure. PredSpec is the predicate spec. for the delayed goal 1769 1770 filter_dg(F/A, Filter, Values) :- 1771 state_filter(Filter, Values), 1772 spied_filter(Filter, Values), 1773 traced_filter(Filter, F/A). 1774 1775 spied_filter(dg_filter{spiedonly:1}, dg_filter{spiedonly:Spied}) ?- !, 1776 Spied == 0'+. 1777 spied_filter(_, _). 1778 1779 state_filter(dg_filter{wakeonly:1}, dg_filter{wakeonly:State}) ?- !, 1780 State == 1. 1781 state_filter(_, _). 1782 1783 traced_filter(dg_filter{traceonly: 1}, F/A) ?- 1784 get_flag(F/A, leash, notrace), !, 1785 fail. 1786 traced_filter(_, _). 1787 1788get_triggers(Ts) :- 1789 findall(T, current_trigger(T), Ts). 1790 1791get_goal_info_by_invoc(Invoc, Spec, TSpec, Module, LookupModule, Path, From, To) :- 1792% TSpec is write transformed goal spec. 1793 find_goal_by_invoc(Invoc, LookupModule, Goal0, Module0, Path0, _Linum, From, To), 1794 (Path0 == '' -> 1795 Path = no 1796 ; 1797 os_file_name(Path0, OSPath), 1798 Path = p(OSPath) 1799 ), 1800 check_at_wrapper(Goal0, Module0, Goal, Module), 1801 getval(dbg_goal_format_string, Mode), 1802 perform_transformation(Goal, Goal, Mode, TGoal, Module), 1803 functor(Goal, F,A), !, 1804 functor(TGoal, TF, TA), 1805 term_string(F/A,Spec), 1806 term_string(TF/TA,TSpec). 1807get_goal_info_by_invoc(_, "unknown", "unknown", "unknown", "unknown","","",""). 1808 1809% this catches any Goal@M calls and returns Goal and M as the goal and module 1810check_at_wrapper(Goal0@M0, _, Goal, M) ?- !, 1811 Goal = Goal0, M = M0. 1812check_at_wrapper(Goal, M, Goal, M). 1813 1814 1815compile_string(String) :- 1816 get_flag(toplevel_module, M), 1817 open(String, string, S), 1818 compile_stream(S)@M, 1819 close(S), 1820 flush(warning_output), % for warnings 1821 flush(error), % for errors 1822 flush(output). % for compiled-messages 1823 1824 1825find_goal_by_invoc(Invoc, DefModule, Goal, Module, Path, Linum, From, To) :- 1826 getval(exec_state, Current), 1827 Current = trace_line{frame:Stack}, 1828 find_goal(Invoc, Stack, Frame), 1829 Frame = tf{goal:Goal, path:Path, line:Linum, from:From, to:To, module:Module}, 1830 get_tf_prop(Frame, module, DefModule). 1831 1832get_ancestors(Anc) :- 1833 getval(exec_state, trace_line{frame:Frame}), 1834 (Frame = tf{parent:Stack} -> 1835 get_ancestors_info(Stack, [], Anc) 1836 % Anc are returned with oldest first; printing in GUI can then 1837 % be from top to bottom 1838 ; Anc = [] % no ancestors, 0'th goal 1839 ). 1840 1841get_ancestors_info(Frame0, Anc0, Anc) :- 1842 (Frame0 == 0 -> % only at depth 0 1843 Anc0 = Anc 1844 1845 ; open(string(""), write, SS), 1846 make_trace_line(SS, trace_line{port:'....',frame:Frame0}, 1847 Depth, _Port, Invoc, Prio, _Path, _Linum, _From, _To), 1848 get_stream_info(SS, name, Line), 1849 close(SS), 1850 Frame0 = tf{parent: PFrame}, 1851 get_ancestors_info(PFrame, [a(Depth,Invoc,Prio,Line)|Anc0], Anc) 1852 ). 1853 1854get_current_traceline(Depth, Style, Line, Invoc) :- 1855 getval(exec_state, Current), 1856 open(string(""), write, SS), 1857 make_trace_line(SS, Current, Depth, Port, Invoc, _Prio, _Path, _Linum, _From, _To), 1858 get_stream_info(SS, name, Line), 1859 close(SS), 1860 port_style(Port, Style). 1861 1862is_current_goal(Invoc, Style) :- 1863 getval(exec_state, trace_line{frame:Frame,port:Port}), 1864 Frame = tf{invoc:Invoc}, 1865 port_style(Port, Style). 1866 1867%------------------------------------------------------------------- 1868% statistics reporting 1869%------------------------------------------------------------------- 1870 1871%:- open(queue(""), update, statistics_out_queue, [yield(on)]). 1872 1873report_stats(Int, Stats) :- 1874 get_memory(Stats, Stats1), 1875 get_times(Stats1), 1876 set_event_handler(stat_report, reporting/0), 1877 event_after_every(stat_report, Int). 1878 1879change_report_interval(New) :- 1880 cancel_after_event(stat_report, _), 1881 event_after_every(stat_report, New). 1882 1883stop_report_stats :- 1884 cancel_after_event(stat_report, _). 1885 1886reporting :- 1887 \+ \+ gen_and_send_stats. % recover memory used when generating stats 1888 1889gen_and_send_stats :- 1890 get_memory(Stats, Stats1), 1891 get_times(Stats1), 1892 write_exdr(statistics_out_queue, Stats), 1893 flush(statistics_out_queue). 1894 1895get_memory(Stats, Tail) :- 1896 get_flag(max_global_trail, MaxGT), 1897 statistics(global_stack_allocated, GAlloc), 1898 statistics(global_stack_used, GUsed), 1899 statistics(global_stack_peak, GPeak), 1900 statistics(trail_stack_allocated, TAlloc), 1901 statistics(trail_stack_used, TUsed), 1902 statistics(trail_stack_peak, TPeak), 1903 get_flag(max_local_control, MaxLC), 1904 statistics(local_stack_allocated, LAlloc), 1905 statistics(local_stack_used, LUsed), 1906 statistics(local_stack_peak, LPeak), 1907 statistics(control_stack_allocated, CAlloc), 1908 statistics(control_stack_used, CUsed), 1909 statistics(control_stack_peak, CPeak), 1910 statistics(shared_heap_allocated, SHAlloc), 1911 statistics(shared_heap_used, SHUsed), 1912% statistics(private_heap_allocated, PHAlloc), 1913% statistics(private_heap_used, PHUsed), 1914 Stats = [[memory, "global and trail stacks", MaxGT, "maximum size of global/trail stacks", stack(global, GAlloc, GUsed, GPeak), stack(trail, TAlloc, TUsed, TPeak)], 1915 [memory, "local and control stacks", MaxLC, "maximum size of local/control stacks", stack(local, LAlloc, LUsed, LPeak), stack(control, CAlloc, CUsed, CPeak)], 1916% [memory, "shared and private heap", SHAlloc, "currently allocated size of shared heap", stack(shared, SHAlloc,SHUsed), stack(private, PHAlloc, PHUsed)] 1917 [memory, "shared heap", SHAlloc, "currently allocated size of shared heap", stack(shared, SHAlloc,SHUsed)] 1918 |Tail]. 1919 1920get_times(Stats) :- 1921 statistics(times, [User, _System, Real]), 1922 statistics(gc_time, GCTime), 1923 statistics(gc_number, NGC), 1924 statistics(gc_collected, Collected), 1925 statistics(gc_ratio, GCRatio), 1926 Stats = [[times, User, Real, gc(GCTime, NGC, Collected, GCRatio)]]. 1927 1928start_report_stats_text_summary(Int) :- 1929 report_stats_text_summary, 1930 stop_report_stats_text_summary, 1931 set_event_handler(stat_report_text_summary, report_stats_text_summary/0), 1932 event_after_every(stat_report_text_summary, Int). 1933 1934stop_report_stats_text_summary :- 1935 cancel_after_event(stat_report_text_summary, _). 1936 1937report_stats_text_summary :- 1938 \+ \+ statistics(statistics_text_summary_queue). 1939 1940 1941%---------------------------------------------------------------------- 1942% source debugging/breakpoints 1943%---------------------------------------------------------------------- 1944 1945file_is_readable(OSFile) :- 1946 os_file_name(File, OSFile), 1947 get_file_info(File, readable, on). % may fail 1948 1949read_file_for_gui(OSFile) :- 1950 os_file_name(File, OSFile), 1951 get_file_info(File, readable, on), % may fail 1952 open(File, read, S), 1953 repeat, 1954 ( read_string(S, end_of_file, 32000, Part) -> 1955 write_exdr(gui_source_file, Part), 1956 flush(gui_source_file), 1957 fail 1958 ; 1959 ! 1960 ), 1961 write_exdr(gui_source_file, ""), 1962 flush(gui_source_file), 1963 close(S). 1964 1965toggle_source_breakpoint(OSFile, Line, PortLine, From, To) :- 1966 os_file_name(File, OSFile), 1967 find_matching_breakport(File, Line, FullName, DMs, PortPreds, PortLine), 1968 ( foreach(PortPred, PortPreds), foreach(DM, DMs), 1969 param(FullName, PortLine, From, To) 1970 do 1971 get_flag(PortPred, break_lines, PInfo)@DM, 1972 ( portline_state(FullName, PortLine, PInfo, From) -> 1973 (From == on -> To = off ; To = on), 1974 set_proc_flags(PortPred, break, PortLine, DM) 1975 ; 1976 % don't toggle if there is a difference in break status 1977 true 1978 ) 1979 ). 1980 1981 portline_state(File,Line, PInfo, From) :- 1982 store_create(Cache), 1983 (member(File0:Line, PInfo), cached_canonical_path_name(File0,File,Cache) -> 1984 From = on 1985 ; 1986 From = off 1987 ). 1988 1989breakpoints_for_file(OSFile, BreakLines, PortLines, Preds) :- 1990 os_file_name(File, OSFile), 1991 get_portlist_from_file(File, port_lines, _, Ports), 1992 get_portlist_from_file(File, break_lines, _, Breaks), 1993 ( foreach(port(PL-_,PredSpec), Ports), 1994 foreach(PL, PortLines), foreach((PredString,PL), Preds0) 1995 do 1996 term_string(PredSpec, PredString) 1997 ), 1998 ( foreach(port(BL-_,_), Breaks), foreach(BL, BreakLines) do true), 1999 sort(1, <, Preds0, Preds). 2000 2001find_matching_callinfo(OSFile, Line, PortPredS, CallSpec) :- 2002 os_file_name(File, OSFile), 2003 % ignore problem with possible multiple modules for the same file 2004 find_matching_breakport(File, Line, FullName, [DM|_], [PortPred|_], PortLine), 2005 get_flag(PortPred, port_lines, LInfos)@DM, 2006 get_flag(PortPred, port_calls, CInfos)@DM, 2007 term_string(PortPred, PortPredS), 2008 get_callinfo(FullName:PortLine, LInfos, CInfos, CallSpec). 2009 2010find_exact_callinfo(OSFile, Line, CallSpec) :- 2011 % OSFile must be an atom 2012 os_file_name(File0, OSFile), 2013 store_create(Cache), 2014 cached_canonical_path_name(File0, File, Cache), 2015 current_predicate_with_port(port_lines, PredSpec, Module, File1:Line), 2016 cached_canonical_path_name(File1, File, Cache), 2017 !, 2018 get_flag(PredSpec, port_lines, LInfos)@Module, 2019 get_flag(PredSpec, port_calls, CInfos)@Module, 2020 get_callinfo(File:Line, LInfos, CInfos, CallSpec). 2021 2022get_callinfo(File:Line, [File0:Line|_], [CallSpec|_], CallSpec) :- 2023 canonical_path_name(File0, File), !. 2024get_callinfo(PredPos, [_|PInfos], [_|CInfos], CallSpec) :- 2025 get_callinfo(PredPos, PInfos, CInfos, CallSpec). 2026 2027% On Windows, canonical_path_name can be really slow! 2028cached_canonical_path_name(Path, CanPath, Cache) :- 2029 ( store_get(Cache, Path, CanPath0) -> 2030 true 2031 ; 2032 canonical_path_name(Path, CanPath0), 2033 store_set(Cache, Path, CanPath0) 2034 ), 2035 CanPath0 = CanPath. 2036 2037%---------------------------------------------------------------------- 2038% Initialise toplevel module 2039%---------------------------------------------------------------------- 2040init_toplevel_module :- 2041 get_flag(toplevel_module, Top), 2042 erase_module(Top), 2043 create_module(Top, [], eclipse_language). 2044 2045%---------------------------------------------------------------------- 2046% Installation - the part that redefines existing toplevel interface 2047% Must be called before gui tools can be used 2048%---------------------------------------------------------------------- 2049 2050install_guitools :- 2051% if trace_line_handler_tcl already set, don't do it again 2052 (get_event_handler(252,trace_line_handler_tcl/2,tracer_tcl) -> 2053 true 2054 ; 2055% openning of these queues now done at attachment 2056% open(queue(""), update, debug_output, [yield(on)]), 2057% open(queue(""), update, debug_traceline, [yield(on)]), 2058 set_default_error_handler(250, trace_start_handler_tcl/0), 2059 reset_event_handler(250), 2060 set_default_error_handler(252, trace_line_handler_tcl/2), 2061 reset_event_handler(252), 2062 2063 get_flag(hostarch, Arch), 2064 ( (Arch == "i386_nt" ; Arch == "x86_64_nt") -> 2065 true 2066 ; 2067 % Catch fatal signals - this is mainly intended for tkeclipse, 2068 % to stop the window from disappearing on such a signal. 2069 % It is important that these are asynchronous handlers which, 2070 % on Unix, execute on their own sigstack. Otherwise they 2071 % wouldn't work on C stack overflow. 2072 ( current_interrupt(_, segv) -> 2073 set_interrupt_handler(segv, catch_fatal/0) ; true ), 2074 ( current_interrupt(_, bus) -> 2075 set_interrupt_handler(bus, catch_fatal/0) ; true ) 2076 ) 2077 ). 2078 2079%---------------------------------------------------------------------- 2080% Uninstallation - undo the installation of guitools' event handlers 2081% Does not try to install another debugger 2082%---------------------------------------------------------------------- 2083 2084uninstall_guitools :- 2085 set_default_error_handler(250, true/0), 2086 reset_event_handler(250), 2087 set_default_error_handler(252, true/0), 2088 reset_event_handler(252). 2089 2090%---------------------------------------------------------------------- 2091% Interrupt handlers 2092%---------------------------------------------------------------------- 2093 2094catch_fatal :- 2095 throw(fatal_signal_caught). 2096 2097%---------------------------------------------------------------------- 2098% Saros Filename involved predicates 2099%---------------------------------------------------------------------- 2100 2101saros_get_library_path(OSDirs) :- 2102 get_flag(library_path,Dirs), 2103 ( foreach(Dir, Dirs), foreach(OSDir, OSDirs) do 2104 os_file_name(Dir, OSDir) 2105 ). 2106 2107saros_set_library_path(OSDirs) :- 2108 ( foreach(OSDir, OSDirs), foreach(Dir, Dirs) do 2109 os_file_name(Dir, OSDir) 2110 ), 2111 set_flag(library_path,Dirs). 2112 2113saros_compile(OSFile) :- 2114 os_file_name(File, OSFile), 2115 compile(File). 2116 2117saros_fcompile(OSFile, OSOutDir) :- 2118 get_flag(toplevel_module, Module), 2119 os_file_name(File, OSFile), 2120 os_file_name(OutDir, OSOutDir), 2121 Options = [compile:no, outdir:OutDir], 2122 fcompile:fcompile(File, Options)@Module. 2123 2124saros_icompile(OSFile, OSOutDir) :- 2125 get_flag(toplevel_module, Module), 2126 os_file_name(File, OSFile), 2127 os_file_name(OutDir, OSOutDir), 2128 document:icompile(File, OutDir)@Module. 2129 2130saros_eci_to_html(OSFile, OSHtmlTopDir, Header) :- 2131 os_file_name(File, OSFile), 2132 os_file_name(HtmlTopDir, OSHtmlTopDir), 2133 document:eci_to_html(File, HtmlTopDir, Header). 2134 2135saros_ecis_to_htmls(OSDirs, OSHtmlTopDir, LinkBack, SystemName) :- 2136 ( is_list(OSDirs) -> 2137 ( foreach(OSDir, OSDirs), foreach(Dir, Dirs) do 2138 os_file_name(Dir, OSDir) 2139 ) 2140 ; 2141 os_file_name(Dirs, OSDirs) 2142 ), 2143 os_file_name(HtmlTopDir, OSHtmlTopDir), 2144 document:ecis_to_htmls(Dirs, HtmlTopDir, LinkBack, SystemName). 2145 2146saros_cd(OSDir) :- 2147 os_file_name(Dir, OSDir), 2148 cd(Dir). 2149 2150saros_use_module(OSFile) :- 2151 os_file_name(File, OSFile), 2152 use_module(File). 2153 2154saros_get_goal_info_by_invoc(Invoc, UseLookupModule, Spec, TSpec, 2155 Module, LookupModule, Path, From, To, Spied) :- 2156 get_goal_info_by_invoc(Invoc, Spec, TSpec, 2157 Module, LookupModule, Path, From, To), 2158 ( LookupModule == "unknown" -> 2159 Spied = "off" 2160 ; 2161 ( UseLookupModule = 1 -> 2162 flag_value(Spec, spy, LookupModule, Spied) 2163 ; 2164 flag_value(Spec, spy, Module, Spied) 2165 ) 2166 ). 2167 2168 2169 2170