[net.sources] Prolog library: helper.pl

pereira@sri-unix.UUCP (08/15/83)

%   File: Mec:Helper.Pl         Author: R.A.O'Keefe      Updated: 12 October 82
%				Modified for TOPS-20	Fernando Pereira

%   This file contains two utilities:
%       try_hard_to_see(FileName, DeviceDefaults, ExtensionDefaults)
%           -- tries all the Extension and Device defaults (varying the
%           -- extensions first) until it succeeds in 'see'ing the file,
%           -- and fails if the file cannot be found.
%       give_help(Area, Topic)
%           -- looks for an assertion help_file(Area, FileName, Delimiter)
%           -- which you must supply.  It then tries hard to open the file
%           -- with default extensions "", "HLP", and "PL" and with device
%           -- defaults "DSK", "MEC", "UTIL", and "PLL".  If the file can't
%           -- be found, or if there is no help_file assertion, it gives an
%           -- apology.  Otherwise it searches the file for the sequence
%           -- Delimiter Topic ".", e.g. #help.
 
%   It defines append, but its definition is the same as that in UTIL.
 
 
%----------------------------------------------------------------------%
 
:- public try_hard_to_see/3.
:- public append/3.
 
:- mode
    try_hard_to_see(+, +, +),
        expand_file(+, +, +, -),
            parse_file(-, -, -, -, ?, ?),
                file_component(-, ?, ?),
                    letter_or_digit(+, -),
            normalise_file_component(+, +, -),
            supply_file_default(+, +, +, -),
                supply_file_default(+, +, -),
            pack_file_title(+, +, +, +, -),
                append(+, +, -).
 
 
try_hard_to_see(Title, DeviceDefaults, ExtensionDefaults) :-
        nofileerrors,
        expand_file(Title, DeviceDefaults, ExtensionDefaults, FullTitle),
        see(FullTitle), !,
        fileerrors.
try_hard_to_see(Title, _, _) :-
        fileerrors,
        write('** Can''t see '), writeq(Title), nl, fail.
 
 
expand_file(Title, DeviceDefaults, ExtensionDefaults, FullTitle) :-
        atomic(Title),  
        name(Title, TitleName), !,
        expand_file(TitleName, DeviceDefaults, ExtensionDefaults, FullTitle).
expand_file(Title, DeviceDefaults, ExtensionDefaults, FullTitle) :-
        parse_file(Device, Directory, FileName, Extension, Title, []),
	normalise_file_component(Directory, 99999, TryDirectory),
        normalise_file_component(FileName, 99999, TryFileName), !,
        supply_file_default(Device, DeviceDefaults, 99999, TryDevice),
        supply_file_default(Extension, ExtensionDefaults, 99999, TryExtension),
        pack_file_title(TryDevice, TryDirectory, TryFileName,
                        TryExtension, TryTitle),
        name(FullTitle, TryTitle).
 
 
        parse_file(Device, Directory, FileName, Extension) -->
                (   file_component(Device), ":"
                |   {   Device = ""   }
                ),  !,
		(   "<", file_component(Directory), ">"
		|    {	Directory = ""	}
		),  !,
                file_component(FileName),
                (   ".", file_component(Extension)
                |   {   Extension = ""   }
                ),  !.
 
 
                file_component([LetDig|Rest]) -->
                        [Char], {   letter_or_digit(Char, LetDig)
				|   [Char] = "-", LetDig = Char  }, !,
                        file_component(Rest).
                file_component([]) --> [].
 
                        letter_or_digit(C, C) :-
                                C >= "0", C =< "9", !.
                        letter_or_digit(C, C) :-
                                C >= "a", C =< "z", !.
                        letter_or_digit(C, D) :-
                                C >= "A", C =< "Z",
                                D is C+("a"-"A").
 
 
        normalise_file_component([], _, []) :- !.
        normalise_file_component(Default, Length, TryThis) :-
                atomic(Default),
                name(Default, DefaultName), !,
                normalise_file_component(DefaultName, Length, TryThis).
        normalise_file_component(_, 0, []) :- !.
        normalise_file_component([C|Rest], Length, [LetDig|More]) :-
                letter_or_digit(C, LetDig), !,
                Left is Length-1,
                normalise_file_component(Rest, Left, More).
        normalise_file_component([_|Rest], Length, TryThis) :-
                normalise_file_component(Rest, Length, TryThis).
 
 
        supply_file_default(Given, _, Length, TryThis) :-
                normalise_file_component(Given, Length, TryThis).
        supply_file_default([], Defaults, Length, TryThis) :-
                supply_file_default(Defaults, Length, TryThis).
 
                supply_file_default([Default|_], Length, TryThis) :-
                        normalise_file_component(Default, Length, TryThis).
                supply_file_default([_|Defaults], Length, TryThis) :- !,
                        supply_file_default(Defaults, Length, TryThis).
 
 
        pack_file_title([], [], FileName, Extension, Title) :- !,
                append(FileName, [46|Extension], Title).        % 46 is "."
        pack_file_title([], Directory, FileName, Extension, Title) :- !,
                pack_file_title([], [], FileName, Extension, Tail),
		append([60|Directory],[62|Tail],Title). 	% 60 is "<"
								% 62 is ">"
        pack_file_title(Device, Directory, FileName, Extension, Title) :-
                pack_file_title([], Directory, FileName, Extension, Tail),
                append(Device, [58|Tail], Title).               % 58 is ":"
 
 
                append([Head|Tail], List, [Head|More]) :-
                        append(Tail, List, More).
                append([], List, List).
 
 
%----------------------------------------------------------------------%
 
:- public give_help/0, give_help/1, give_help/2.
 
:- mode
    give_help,                          %  list of areas.
    give_help(+),                       %  list of topics in an area.
    give_help(+, +),                    %  help on a specific topic.
        find_help(+, +),                %  find and type a topic of list
            read_after_delimiter(+),    %  find "#" or return end_of_file
            find_help(+, +, +),         %  check a list of topics
                among(+, +),            %  member on commas instead of dots
                type_until_delimiter(+). %  display body of a Note.
 
 
 
give_help :-
        write('Help is available in the following areas:'), nl,
        help_file(Area, _, _),
        tab(4), writeq(Area), nl,
        fail.
give_help :-
        write('Call give_help(Area) for a list of topics in an Area.'), nl,
        write('Call give_help('), write('Area'),
        write(',Topic) for help about a specific topic.'), nl.
 
 
give_help(Area) :-
        write('The topics in '), writeq(Area),
        write(' for which help is available are:'), nl,
        give_help(Area, Topic),
        write('Call give_help('), writeq(Area),
        write(',Topic) for help about a specific topic.'), nl.
 
give_help(Area, Topic) :-
        (   help_file(Area, HelpName, Delimiter),
                call(Delim is Delimiter)
        |   atom(Area),
                Delim is "#", HelpName = Area
        ),
        seeing(Old),
        (   try_hard_to_see(HelpName, [dsk,mec,util,pll], [hlp,pl]), !,
                find_help(Delim, Topic),
                seen,
                see(Old)
        |    write('** No help is available on '), writeq(Topic),
                write(' in '), writeq(Area), nl
        ),  !.
 
 
        find_help(Delimiter, Topic) :-
                var(Topic), !,
                read_after_delimiter(Delimiter, Topics),
                (   Topics = end_of_file
                |   tab(4), write(Topics), nl, fail
                ).
        find_help(Delimiter, Topic) :-
                read_after_delimiter(Delimiter, Topics),
                find_help(Topics, Topic, Delimiter).
 
                find_help(end_of_file, Topic, _) :- !,
                        seeing(HelpFile),
                        write('** No help is available on '), writeq(Topic),
                        write(' in file '), writeq(HelpFile), nl.
                find_help(Topics, Topic, Delimiter) :-
                        among(Topic, Topics),
                        type_until_delimiter(Delimiter).
 
 
                among(Topic, (Topics1,Topics2)) :- !,
                        (   among(Topic, Topics1)
                        |   among(Topic, Topics2)
                        ).
                among(Topic, (Topics1;Topics2)) :- !,
                        (   among(Topic, Topics1)
                        |   among(Topic, Topics2)
                        ).
                among(Topic, Topic).
 
 
                read_after_delimiter(Delimiter, Topics) :-
                        repeat,
                                get0(Character),
                                (   Character = 26, !, Topics = end_of_file
                                |   Character = Delimiter, read(Topics)
                                ).
 
 
                type_until_delimiter(Delimiter) :-
                        get0(C),
                        C =\= 26, C =\= Delimiter,
                        put(C), !,
                        type_until_delimiter(Delimiter).
                type_until_delimiter(Delimiter).
        
 
/*                                                      DEBUGGING CODE
is_string(X) :-
        var(X), !, fail.
is_string([]) :- !.
is_string([H|_]) :-
        \+ integer(H), !, fail.
is_string([9|T]) :-
        is_string(T).
is_string([H|T]) :-
        32 =< H, H < 127,
        is_string(T).
 
portray_string([]) :-
        put(34).
portray_string([34|T]) :-
        put(34), put(34), !,
        portray_string(T).
portray_string([H|T]) :-
        put(H), !,
        portray_string(T).
 
portray(X) :-
        is_string(X),
        put(34),
        portray_string(X).
 
try(T) :-
        expand_file(T, [dsk, mec, util, pll], [hlp, txt], Title),
        writeq(Title), nl,
        fail.
 
/*                                              DEBUGGING CODE */