1 /* SWI-Prolog Common Foreign Language Interface.
2    Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3    Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4 
5 This file is part of the Parma Polyhedra Library (PPL).
6 
7 The PPL is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3 of the License, or (at your
10 option) any later version.
11 
12 The PPL is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15 for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20 
21 For the most up-to-date information see the Parma Polyhedra Library
22 site: http://bugseng.com/products/ppl/ . */
23 
24 #ifndef PCFLI_swi_cfli_hh
25 #define PCFLI_swi_cfli_hh 1
26 
27 /* Include gmp.h before SWI-Prolog.h.  This is required in order to
28    get access to interface functions dealing with GMP numbers and
29    SWI-Prolog terms.  */
30 #include <gmp.h>
31 #include <SWI-Prolog.h>
32 #include <cassert>
33 #include <climits>
34 
35 typedef term_t Prolog_term_ref;
36 typedef atom_t Prolog_atom;
37 typedef foreign_t Prolog_foreign_return_type;
38 
39 const Prolog_foreign_return_type PROLOG_SUCCESS = TRUE;
40 const Prolog_foreign_return_type PROLOG_FAILURE = FALSE;
41 
42 /*!
43   Return a new term reference.
44 */
45 inline Prolog_term_ref
Prolog_new_term_ref()46 Prolog_new_term_ref() {
47   return PL_new_term_ref();
48 }
49 
50 /*!
51   Make \p t be a reference to the same term referenced by \p u,
52   i.e., assign \p u to \p t.
53 */
54 inline int
Prolog_put_term(Prolog_term_ref t,Prolog_term_ref u)55 Prolog_put_term(Prolog_term_ref t, Prolog_term_ref u) {
56 #if PLVERSION >= 50800
57   return PL_put_term(t, u);
58 #else
59   PL_put_term(t, u);
60   return 1;
61 #endif
62 }
63 
64 /*!
65   Assign to \p t a Prolog integer with value \p l.
66 */
67 inline int
Prolog_put_long(Prolog_term_ref t,long l)68 Prolog_put_long(Prolog_term_ref t, long l) {
69 #if PLVERSION >= 50800
70   return PL_put_integer(t, l);
71 #else
72   PL_put_integer(t, l);
73   return 1;
74 #endif
75 }
76 
77 static int tmp_mpz_t_initialized = 0;
78 static mpz_t tmp_mpz_t;
79 
80 /*!
81   Assign to \p t a Prolog integer with value \p ul.
82 */
83 static int
Prolog_put_big_ulong(Prolog_term_ref t,unsigned long ul)84 Prolog_put_big_ulong(Prolog_term_ref t, unsigned long ul) {
85   assert(ul > LONG_MAX && ul > (uint64_t) INT64_MAX);
86   if (!tmp_mpz_t_initialized) {
87     mpz_init_set_ui(tmp_mpz_t, ul);
88     tmp_mpz_t_initialized = 1;
89   }
90   else
91     mpz_set_ui(tmp_mpz_t, ul);
92   return PL_unify_mpz(t, tmp_mpz_t);
93 }
94 
95 /*!
96   Assign to \p t a Prolog integer with value \p ul.
97 */
98 inline int
Prolog_put_ulong(Prolog_term_ref t,unsigned long ul)99 Prolog_put_ulong(Prolog_term_ref t, unsigned long ul) {
100   if (ul <= LONG_MAX) {
101 #if PLVERSION >= 50800
102     return PL_put_integer(t, ul);
103 #else
104     PL_put_integer(t, ul);
105     return 1;
106 #endif
107   }
108   else if (ul <= (uint64_t) INT64_MAX) {
109 #if PLVERSION >= 50800
110     return PL_put_int64(t, (int64_t) ul);
111 #else
112     PL_put_int64(t, (int64_t) ul);
113     return 1;
114 #endif
115   }
116   else
117     return Prolog_put_big_ulong(t, ul);
118 }
119 
120 /*!
121   Assign to \p t an atom whose name is given
122   by the null-terminated string \p s.
123 */
124 inline int
Prolog_put_atom_chars(Prolog_term_ref t,const char * s)125 Prolog_put_atom_chars(Prolog_term_ref t, const char* s) {
126 #if PLVERSION >= 50800
127   return PL_put_atom_chars(t, s);
128 #else
129   PL_put_atom_chars(t, s);
130   return 1;
131 #endif
132 }
133 
134 /*!
135   Assign to \p t the Prolog atom \p a.
136 */
137 inline int
Prolog_put_atom(Prolog_term_ref t,Prolog_atom a)138 Prolog_put_atom(Prolog_term_ref t, Prolog_atom a) {
139 #if PLVERSION >= 50800
140   return PL_put_atom(t, a);
141 #else
142   PL_put_atom(t, a);
143   return 1;
144 #endif
145 }
146 
147 /*!
148   Assign to \p t the list terminator <CODE>[]</CODE> (which needs not
149   be an atom).
150 */
151 inline int
Prolog_put_nil(Prolog_term_ref t)152 Prolog_put_nil(Prolog_term_ref t) {
153   PL_put_nil(t);
154   return 1;
155 }
156 
157 /*!
158   Assign to \p t a term representing the address contained in \p p.
159 */
160 inline int
Prolog_put_address(Prolog_term_ref t,void * p)161 Prolog_put_address(Prolog_term_ref t, void* p) {
162 #if PLVERSION >= 50800
163   return PL_put_pointer(t, p);
164 #else
165   PL_put_pointer(t, p);
166   return 1;
167 #endif
168 }
169 
170 /*!
171   Return an atom whose name is given by the null-terminated string \p s.
172 */
173 inline Prolog_atom
Prolog_atom_from_string(const char * s)174 Prolog_atom_from_string(const char* s) {
175   return PL_new_atom(s);
176 }
177 
178 /*!
179   Assign to \p t a compound term whose principal functor is \p f
180   of arity 1 with argument \p a1.
181 */
182 inline int
Prolog_construct_compound(Prolog_term_ref t,Prolog_atom f,Prolog_term_ref a1)183 Prolog_construct_compound(Prolog_term_ref t, Prolog_atom f,
184                           Prolog_term_ref a1) {
185 #if PLVERSION >= 50800
186   return PL_cons_functor(t, PL_new_functor(f, 1), a1);
187 #else
188   PL_cons_functor(t, PL_new_functor(f, 1), a1);
189   return 1;
190 #endif
191 }
192 
193 /*!
194   Assign to \p t a compound term whose principal functor is \p f
195   of arity 2 with arguments \p a1 and \p a2.
196 */
197 inline int
Prolog_construct_compound(Prolog_term_ref t,Prolog_atom f,Prolog_term_ref a1,Prolog_term_ref a2)198 Prolog_construct_compound(Prolog_term_ref t, Prolog_atom f,
199                           Prolog_term_ref a1, Prolog_term_ref a2) {
200 #if PLVERSION >= 50800
201   return PL_cons_functor(t, PL_new_functor(f, 2), a1, a2);
202 #else
203   PL_cons_functor(t, PL_new_functor(f, 2), a1, a2);
204   return 1;
205 #endif
206 }
207 
208 /*!
209   Assign to \p t a compound term whose principal functor is \p f
210   of arity 3 with arguments \p a1, \p a2 and \p a3.
211 */
212 inline int
Prolog_construct_compound(Prolog_term_ref t,Prolog_atom f,Prolog_term_ref a1,Prolog_term_ref a2,Prolog_term_ref a3)213 Prolog_construct_compound(Prolog_term_ref t, Prolog_atom f,
214                           Prolog_term_ref a1, Prolog_term_ref a2,
215                           Prolog_term_ref a3) {
216 #if PLVERSION >= 50800
217   return PL_cons_functor(t, PL_new_functor(f, 3), a1, a2, a3);
218 #else
219   PL_cons_functor(t, PL_new_functor(f, 3), a1, a2, a3);
220   return 1;
221 #endif
222 }
223 
224 /*!
225   Assign to \p t a compound term whose principal functor is \p f
226   of arity 4 with arguments \p a1, \p a2, \p a3 and \p a4.
227 */
228 inline int
Prolog_construct_compound(Prolog_term_ref t,Prolog_atom f,Prolog_term_ref a1,Prolog_term_ref a2,Prolog_term_ref a3,Prolog_term_ref a4)229 Prolog_construct_compound(Prolog_term_ref t, Prolog_atom f,
230                           Prolog_term_ref a1, Prolog_term_ref a2,
231                           Prolog_term_ref a3, Prolog_term_ref a4) {
232 #if PLVERSION >= 50800
233   return PL_cons_functor(t, PL_new_functor(f, 4), a1, a2, a3, a4);
234 #else
235   PL_cons_functor(t, PL_new_functor(f, 4), a1, a2, a3, a4);
236   return 1;
237 #endif
238 }
239 
240 /*!
241   Assign to \p c a Prolog list whose head is \p h and tail is \p t.
242 */
243 inline int
Prolog_construct_cons(Prolog_term_ref c,Prolog_term_ref h,Prolog_term_ref t)244 Prolog_construct_cons(Prolog_term_ref c,
245                       Prolog_term_ref h, Prolog_term_ref t) {
246 #if PLVERSION >= 50800
247   return PL_cons_list(c, h, t);
248 #else
249   PL_cons_list(c, h, t);
250   return 1;
251 #endif
252 }
253 
254 /*!
255   Raise a Prolog exception with \p t as the exception term.
256 */
257 inline void
Prolog_raise_exception(Prolog_term_ref t)258 Prolog_raise_exception(Prolog_term_ref t) {
259   (void) PL_raise_exception(t);
260 }
261 
262 /*!
263   Return true if \p t is a Prolog variable, false otherwise.
264 */
265 inline int
Prolog_is_variable(Prolog_term_ref t)266 Prolog_is_variable(Prolog_term_ref t) {
267   return PL_is_variable(t);
268 }
269 
270 /*!
271   Return true if \p t is a Prolog atom, false otherwise.
272 */
273 inline int
Prolog_is_atom(Prolog_term_ref t)274 Prolog_is_atom(Prolog_term_ref t) {
275   return PL_is_atom(t);
276 }
277 
278 /*!
279   Return true if \p t is a Prolog integer, false otherwise.
280 */
281 inline int
Prolog_is_integer(Prolog_term_ref t)282 Prolog_is_integer(Prolog_term_ref t) {
283   return PL_is_integer(t);
284 }
285 
286 /*!
287   Return true if \p t is the representation of an address, false otherwise.
288 */
289 inline int
Prolog_is_address(Prolog_term_ref t)290 Prolog_is_address(Prolog_term_ref t) {
291   return PL_is_integer(t);
292 }
293 
294 /*!
295   Return true if \p t is a Prolog compound term, false otherwise.
296 */
297 inline int
Prolog_is_compound(Prolog_term_ref t)298 Prolog_is_compound(Prolog_term_ref t) {
299   return PL_is_compound(t);
300 }
301 
302 /*!
303   Return true if \p t is a Prolog cons (list constructor), false otherwise.
304 */
305 inline int
Prolog_is_cons(Prolog_term_ref t)306 Prolog_is_cons(Prolog_term_ref t) {
307   return PL_is_pair(t);
308 }
309 
310 /*!
311   Assuming \p t is a Prolog integer, return true if its value fits
312   in a long, in which case the value is assigned to \p v,
313   return false otherwise.  The behavior is undefined if \p t is
314   not a Prolog integer.
315 */
316 inline int
Prolog_get_long(Prolog_term_ref t,long * lp)317 Prolog_get_long(Prolog_term_ref t, long* lp) {
318   assert(Prolog_is_integer(t));
319   return PL_get_long(t, lp);
320 }
321 
322 /*!
323   If \p t is the Prolog representation for a memory address, return
324   true and store that address into to \p v; return false otherwise.
325   The behavior is undefined if \p t is not an address.
326 */
327 inline int
Prolog_get_address(Prolog_term_ref t,void ** vpp)328 Prolog_get_address(Prolog_term_ref t, void** vpp) {
329   assert(Prolog_is_address(t));
330   return PL_get_pointer(t, vpp);
331 }
332 
333 /*!
334   If \p t is a Prolog atom, return true and store its name into \p name.
335   The behavior is undefined if \p t is not a Prolog atom.
336 */
337 inline int
Prolog_get_atom_name(Prolog_term_ref t,Prolog_atom * ap)338 Prolog_get_atom_name(Prolog_term_ref t, Prolog_atom* ap) {
339   assert(Prolog_is_atom(t));
340   return PL_get_atom(t, ap);
341 }
342 
343 /*!
344   If \p t is a Prolog compound term, return true and store its name
345   and arity into \p name and \p arity, respectively.
346   The behavior is undefined if \p t is not a Prolog compound term.
347 */
348 inline int
Prolog_get_compound_name_arity(Prolog_term_ref t,Prolog_atom * ap,int * ip)349 Prolog_get_compound_name_arity(Prolog_term_ref t, Prolog_atom* ap, int* ip) {
350   assert(Prolog_is_compound(t));
351   return PL_get_name_arity(t, ap, ip);
352 }
353 
354 /*!
355   If \p t is a Prolog compound term and \p i is a positive integer
356   less than or equal to its arity, return true and assign to \p a the
357   i-th (principal) argument of \p t.
358   The behavior is undefined if \p t is not a Prolog compound term.
359 */
360 inline int
Prolog_get_arg(int i,Prolog_term_ref t,Prolog_term_ref a)361 Prolog_get_arg(int i, Prolog_term_ref t, Prolog_term_ref a) {
362   assert(Prolog_is_compound(t));
363   return PL_get_arg(i, t, a);
364 }
365 
366 /*!
367   Succeeds if and only if \p t represents the list terminator <CODE>[]</CODE>
368   (which needs not be an atom).
369 */
370 inline int
Prolog_get_nil(Prolog_term_ref t)371 Prolog_get_nil(Prolog_term_ref t) {
372   return PL_get_nil(t);
373 }
374 
375 /*!
376   If \p c is a Prolog cons (list constructor), assign its head and
377   tail to \p h and \p t, respectively.
378   The behavior is undefined if \p c is not a Prolog cons.
379 */
380 inline int
Prolog_get_cons(Prolog_term_ref c,Prolog_term_ref h,Prolog_term_ref t)381 Prolog_get_cons(Prolog_term_ref c, Prolog_term_ref h, Prolog_term_ref t) {
382   assert(Prolog_is_cons(c));
383   return PL_get_list(c, h, t);
384 }
385 
386 /*!
387   Unify the terms referenced by \p t and \p u and return true
388   if the unification is successful; return false otherwise.
389 */
390 inline int
Prolog_unify(Prolog_term_ref t,Prolog_term_ref u)391 Prolog_unify(Prolog_term_ref t, Prolog_term_ref u) {
392   return PL_unify(t, u);
393 }
394 
395 #endif // !defined(PCFLI_swi_cfli_hh)
396