:- module(foreign).
:- export make_simple_interface / 2.
:- export make_simple_interface_body / 1.
:- export load_foreign_files / 3.
:- export make_simple_interface / 1.
:- export make_simple_interface / 0.
:- export load_foreign_files / 2.
:- export tr_foreign / 3.
:- export declare_externals / 2.
:- export declare_externals / 1.
:- export macro(foreign / 3, foreign : tr_foreign / 3, [clause]).
:- tool(make_simple_interface / 1,make_simple_interface / 2).
:- tool(make_simple_interface / 0,make_simple_interface_body / 1).
:- tool(load_foreign_files / 2,load_foreign_files / 3).
:- tool(declare_externals / 1,declare_externals / 2).
:- comment(make_simple_interface / 2, hidden).
:- comment(make_simple_interface_body / 1, hidden).
:- comment(load_foreign_files / 3, hidden).
:- comment(declare_externals / 2, hidden).
:- comment(summary, "Simple foreign interface like SICStus or Quintus").
:- comment(author, "Micha Meier, ECRC Munich").
:- comment(copyright, "Cisco Systems, Inc").
:- comment(date, "$Date: 2006/09/23 01:55:18 $").
:- comment(desc, ascii("\nSimple foreign interface like SICStus or Quintus(TM). For every C function\nan interface C function is generated which converts the arguments\nfrom and to the Sepia ones. Note that this is faster (and uses more\nC code) than one generic interface procedure which dispatches all\nexternal calls like in the above systems. Use it as follows:\n\n1) load this file with lib(foreign)\n2) compile (Sepia) the file with the foreign/3 clauses\n3) call make_simple_interface/0 or /1; this will generate the file\n   e_interface.c\n4) compile (cc) e_interface.c and the other C source files\n      On a SVR4 system (e.g. Solaris 2.x) produce one .so file\n      from all the .o files that should be loaded, including\n      the file e_interface.o. On Solaris this can be done with\n      something like\n\tcc -I$ECLIPSEDIR/include -G -o myfile.so file1.c file2.c \t\t... e_interface.c\n5) call load_foreign_files/2. This assumes that the foreign/3 clauses\n   are still available.\n\nThis means that a file which contains both foreign/3 facts and\na goal :- load_foreign_files(...) must be split so that\nmake_simple_interface/0 can be called before the goal.\nHowever, once the file e_interface.c is created, this file can be used\nin the original form.\n\nThe main purpose of the interface is to port foreign files from\nSICStus or Quintus to Sepia, or to automate interfacing of\nother existing C functions. When writing new external functions,\nit is more efficient to use the Sepia external interface directly.\n\n\nUser-defined types and conversion can also be specified.\nIf some additional declarations and function calls are necessary\nbefore or after calling the C function, the type can be specified\nas a user type:\n\t[+-]user(Type)\n\nWhen such a type is encountered, this library will call the predicate\n\nforeign_user_type(+Type, +I, -CType, -Local, -TypeCheck, -InConv,\n\t-Call, -OutConv, -Unif)\n\nwhich is supposed to yield the data to be inserted into the\nsource of the interface file. The arguments are as follows:\nType\t- the name of the user type with + or -, e.g. +mystring\nI\t- the argument position; used to make distinction\n\t  among several args of the same type\nCType\t- the corresponding C type\nLocal\t- declaration of local variables for this type\nTypeCheck - type testing of the predicate arguments\nInConv\t- calls to be made before calling the foreign function\nCall\t- the actual argument passed to the foreign function\nOutConv\t- calls to be made after the foreign call and before\n\t  the unification of output arguments\nUnif\t- unification of the output argument\n\nThe source of the generated interface for a declaration\nforeign(funct, c, funct(+integer, +user(ut)))\nlooks as follows:\n\np_funct(val1, tag1, val2, tag2)\nvalue\tval1, val2;\ntype\ttag1, tag2;\n{\n\tLOCAL\n\n\tCheck_Integer(tag1);\n\tTYPECHECK\n\tINCONV\n\tfunct(val1.nint, CALL)\n\tOUTCONV\n\tReturn_UNIF\n}\nwhere the capitalized ids are substituted by the user definition.\n")).
