#!/usr/bin/swipl :- set_prolog_flag(verbose, silent). :- initialization main. /* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This file emulates SICStus the splfr program, which extracts declarations for foreign resources from a Prolog file, creates a wrapper, compiles this and finally generates a shared object that is automatically loaded into SWI-Prolog. Note that this implementation is only partial. It was written for running Alpino (www.let.rug.nl/vannoord/alp/Alpino/) and only processes the commandline options needed for this. To use this facility, copy this file to a directory in your $PATH and edit the first line to reflect the location of SWI-Prolog. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */ :- use_module(library(prolog_source)). :- use_module(library(qpforeign)). :- use_module(library(apply)). :- use_module(library(debug)). :- use_module(library(option)). :- debug(swipl_frl). main :- current_prolog_flag(argv, Argv), ( catch(swipl_frl(Argv), Error, ( print_message(error, Error), halt(1) )) -> halt ; print_message(error, goal_failed(swipl_frl(Argv))), halt(1) ). swipl_frl(Av) :- partition(longoption, Av, LongOptions, Av2), maplist(longoption, LongOptions, NVList), partition(plfile, Av2, PlFiles, Rest), PlFiles = [PlFile], file_name_extension(Base, _Ext, PlFile), create_glue(PlFile, GlueFile), option(cflag(CFlags), NVList, ''), atomic_list_concat([GlueFile,CFlags|Rest], ' ', Cmd0), format(atom(Cmd), 'swipl-ld -shared -o ~w ~w', [Base, Cmd0]), debug(swipl_frl, '~w', [Cmd]), shell(Cmd). plfile(Name) :- \+ sub_atom(Name, 0, _, _, -), file_name_extension(_, pl, Name). longoption(Name) :- sub_atom(Name, 0, _, _, --). longoption(Option, Name=Value) :- atom_concat(--, Rest, Option), sub_atom(Rest, B, _, A, =), sub_atom(Rest, 0, B, _, Name), sub_atom(Rest, _, A, 0, Value). %% create_glue(+PrologFile, -GlueFile) is det % % Create the glue foreign resources in PrologFile. The glue is % written to GlueFile. create_glue(File, Glue) :- file_name_extension(Base, _Ext, File), atom_concat(Base, '_swi_glue', GlueBase), file_name_extension(GlueBase, c, Glue), load_resource_decls(File, Module), create_module_glue(Module, Base, GlueBase). create_module_glue(Module, Base, GlueBase) :- Module:foreign_resource(Resource, _), make_foreign_resource_wrapper(Module:Resource, Base, GlueBase). %% load_resource_decls(+Source, -Module) % % Load SICSTus/Quintus resource declarations from Source. Module % is the module in which the resources are loaded. load_resource_decls(Source, Module) :- expects_dialect(sicstus), prolog_canonical_source(Source, Id), setup_call_cleanup(prolog_open_source(Id, In), process(In, no_module, Module), prolog_close_source(In)). process(In, State0, Module) :- prolog_read_source_term(In, _, Expanded, []), process_terms(Expanded, State0, State1), ( State1 = end_of_file(EndState) -> state_module(EndState, Module) ; process(In, State1, Module) ). process_terms([], State, State) :- !. process_terms([H|T], State0, State) :- !, process_term(H, State0, State1), ( State1 == end_of_file -> State = State1 ; process_terms(T, State1, State) ). process_terms(T, State0, State) :- process_term(T, State0, State). process_term(end_of_file, State, end_of_file(State)) :- !. process_term((:- module(Name, _)), _, module(Name)) :- !, clean_resources(Name). process_term(Term, State, State) :- foreign_term(Term, Assert), !, state_module(State, M), assertz(M:Assert). process_term(_, State, State). foreign_term(foreign_resource(Name, Funcs), foreign_resource(Name, Funcs)). foreign_term(foreign(Func, Pred), foreign(Func, c, Pred)). foreign_term(foreign(Func, Lang, Pred), foreign(Func, Lang, Pred)). state_module(module(M), M). state_module(no_module, user). clean_resources(Module) :- forall(foreign_term(_, T), Module:retractall(T)).