Porting PiLLoW 1.1 to Quintus Prolog 3.X

If you want to port PiLLoW 1.1 to Quintus Prolog, the following notes may be of use.

http_transaction/5

http_transaction/5 must be rewritten to use the Quintus tcp and socketio libraries.

http_transaction(+Host, +Port, +Request, +Timeout, -Response) Sends an HTTP Request to an HTTP server (Host:Port) and returns the resultant message in Response.

:- use_module(library(tcp)).
:- use_module(library(socketio)).
:- use_module(library(date), [now/1]).

http_transaction( Host, Port, Request, Timeout, Response ) :-
    connect( Host, Port, Socket ),
    Socket >= 0,  % Fail if connect error
    socket_io_open_output( Socket, Ocode ),
    stream_code( OStream, Ocode ),
    write_string( OStream, Request ),
    close( OStream ),
    socket_io_open_input( Socket, Icode ),
    stream_code( IStream, Icode ),
    now( Now ),
    http_transaction1( Now, Socket, IStream, Timeout, Response ),
    close( IStream ),
    tcp_shutdown( Socket, _Status ),
    Response \== timeout.

http_transaction1( Now, Socket, IStream, Timeout, Response ) :-
    tcp_select( 0, Timeout, FD, Status ),
    http_transaction2( Status, Now, Socket, FD, IStream, Timeout, Response ).

http_transaction2( 1, Then, Socket, FD, IStream, Timeout, Response ) :-
    ( Socket == FD ->
        read_to_close( IStream, Response )
    ; otherwise ->
        now( Now ),
        Elapsed is Now - Then,
        ( Elapsed < Timeout ->
            Timeout1 is Timeout - Elapsed,
            http_transaction1( Now, Socket, IStream, Timeout1, Response )
        ; otherwise ->
            Response = timeout
        )
    ).
http_transaction2( 0, _Then, _Socket, _FD, _IStream, _Timeout, timeout ).
http_transaction2( -1, _Then, Socket, _FD, IStream, Timeout, _Response ) :-
    raise_exception( socket_error(Socket, IStream, Timeout) ).

foreign(tcp_connect,c,connect(+string,+integer,[-integer])).
foreign(tcp_select, c, tcp_select(+integer, +double, -integer, [-integer])).
foreign(tcp_shutdown,c,tcp_shutdown(+integer,[-integer])).

foreign_file(library(system(tcp_p)),[
    tcp_connect,
    tcp_select,
    tcp_shutdown
    ]).

:- load_foreign_executable(library(system(tcp_p))),
   abolish(foreign_file, 2),
   abolish(foreign, 3).

A number of ISO Prolog predicates are used. These can be mapped to equivalent Quintus built-in predicates:

flush_output :-
    ttyflush.

atom_codes( Atom, Codes ) :-
    atom_chars( Atom, Codes ).

catch( Goal, Error, Action ) :-
    on_exception( Error, Goal, Action ).

get_code( Code ) :-
    get0( Code ).

get_code( Stream, Code ) :-
    get0( Stream, Code ).

include( File ) :-
    ensure_loaded( File ).

number_codes( Number, Codes ) :-
    number_chars( Number, Codes ).

put_code( Code ) :-
    put( Code ).

Similarly, some library predicates are not defined/defined differently in Quintus:

atom_concat( A, B, AB ) :-
    name( A, AS ),
    name( B, BS ),
    append( AS, BS, ABS ),
    atom_chars( AB, ABS ).

getenv( Var, QueryString ) :-
    environ( Var, QueryString ).

:- use_module( library(environ), [environ/2] ).