1/* SICStus Common Foreign Language Interface: definitions. -*- C -*-
2   Copyright (C) 2001-2010 Roberto Bagnara <bagnara@cs.unipr.it>
3   Copyright (C) 2010-2016 BUGSENG srl (http://bugseng.com)
4
5This file is part of the Parma Polyhedra Library (PPL).
6
7The PPL is free software; you can redistribute it and/or modify it
8under the terms of the GNU General Public License as published by the
9Free Software Foundation; either version 3 of the License, or (at your
10option) any later version.
11
12The PPL is distributed in the hope that it will be useful, but WITHOUT
13ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with this program; if not, write to the Free Software Foundation,
19Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307, USA.
20
21For the most up-to-date information see the Parma Polyhedra Library
22site: http://bugseng.com/products/ppl/ . */
23
24#include <assert.h>
25#include <limits.h>
26
27/*!
28  Return a new term reference.
29*/
30PCFLI_EXTERN_INLINE Prolog_term_ref
31Prolog_new_term_ref() {
32  return SP_new_term_ref();
33}
34
35/*!
36  Make \p t be a reference to the same term referenced by \p u,
37  i.e., assign \p u to \p t.
38*/
39PCFLI_EXTERN_INLINE int
40Prolog_put_term(Prolog_term_ref t, Prolog_term_ref u) {
41  return SP_put_term(t, u);
42}
43
44/*!
45  Assign to \p t a Prolog integer with value \p l.
46*/
47PCFLI_EXTERN_INLINE int
48Prolog_put_long(Prolog_term_ref t, long l) {
49  return SP_put_integer(t, l);
50}
51
52static int
53Prolog_put_big_ulong(Prolog_term_ref t, unsigned long ul) {
54  static unsigned char uc_buffer[sizeof(unsigned long) + 1];
55  static unsigned n;
56#if PPL_SIZEOF_LONG_LONG > PPL_SIZEOF_LONG
57  static long long ll_buffer;
58#endif
59
60#if PPL_SIZEOF_LONG_LONG > PPL_SIZEOF_LONG
61  ll_buffer = ul;
62  if (SP_put_integer_bytes(t, &ll_buffer, sizeof(ll_buffer), 1))
63    return 1;
64#endif
65  n = 0;
66  do {
67    uc_buffer[n++] = ul & 0xff;
68    ul >>= 8;
69  } while (ul);
70  if (uc_buffer[n-1] & 0x80)
71    uc_buffer[n++] = 0;
72  return SP_put_integer_bytes(t, &uc_buffer, n, 0);
73}
74
75/*!
76  Assign to \p t a Prolog integer with value \p ul.
77*/
78PCFLI_EXTERN_INLINE int
79Prolog_put_ulong(Prolog_term_ref t, unsigned long ul) {
80  return
81    (ul <= LONG_MAX)
82    ? SP_put_integer(t, (long) ul)
83    : Prolog_put_big_ulong(t, ul);
84}
85
86/*!
87  Assign to \p t an atom whose name is given
88  by the null-terminated string \p s.
89*/
90PCFLI_EXTERN_INLINE int
91Prolog_put_atom_chars(Prolog_term_ref t, const char* s) {
92  return SP_put_string(t, s);
93}
94
95/*!
96  Assign to \p t the Prolog atom \p a.
97*/
98PCFLI_EXTERN_INLINE int
99Prolog_put_atom(Prolog_term_ref t, Prolog_atom a) {
100  return SP_put_atom(t, a);
101}
102
103/*!
104  Assign to \p t a term representing the address contained in \p p.
105*/
106PCFLI_EXTERN_INLINE int
107Prolog_put_address(Prolog_term_ref t, void* p) {
108  return SP_put_address(t, p);
109}
110
111/*!
112  Return an atom whose name is given by the null-terminated string \p s.
113*/
114PCFLI_EXTERN_INLINE Prolog_atom
115Prolog_atom_from_string(const char* s) {
116  return SP_atom_from_string(s);
117}
118
119/*!
120  Assign to \p t a compound term whose principal functor is \p f
121  of arity 1 with argument \p a1.
122*/
123PCFLI_EXTERN_INLINE int
124Prolog_construct_compound(Prolog_term_ref t, Prolog_atom f,
125                          Prolog_term_ref a1) {
126  return SP_cons_functor(t, f, 1, a1);
127}
128
129/*!
130  Assign to \p t a compound term whose principal functor is \p f
131  of arity 2 with arguments \p a1 and \p a2.
132*/
133PCFLI_EXTERN_INLINE int
134Prolog_construct_compound(Prolog_term_ref t, Prolog_atom f,
135                          Prolog_term_ref a1, Prolog_term_ref a2) {
136  return SP_cons_functor(t, f, 2, a1, a2);
137}
138
139/*!
140  Assign to \p t a compound term whose principal functor is \p f
141  of arity 3 with arguments \p a1, \p a2 and \p a3.
142*/
143PCFLI_EXTERN_INLINE int
144Prolog_construct_compound(Prolog_term_ref t, Prolog_atom f,
145                          Prolog_term_ref a1, Prolog_term_ref a2,
146                          Prolog_term_ref a3) {
147  return SP_cons_functor(t, f, 3, a1, a2, a3);
148}
149
150/*!
151  Assign to \p t a compound term whose principal functor is \p f
152  of arity 4 with arguments \p a1, \p a2, \p a3 and \p a4.
153*/
154PCFLI_EXTERN_INLINE int
155Prolog_construct_compound(Prolog_term_ref t, Prolog_atom f,
156                          Prolog_term_ref a1, Prolog_term_ref a2,
157                          Prolog_term_ref a3, Prolog_term_ref a4) {
158  return SP_cons_functor(t, f, 4, a1, a2, a3, a4);
159}
160
161/*!
162  Assign to \p c a Prolog list whose head is \p h and tail is \p t.
163*/
164PCFLI_EXTERN_INLINE int
165Prolog_construct_cons(Prolog_term_ref c,
166                      Prolog_term_ref h, Prolog_term_ref t) {
167  return SP_cons_list(c, h, t);
168}
169
170/*!
171  Raise a Prolog exception with \p t as the exception term.
172*/
173PCFLI_EXTERN_INLINE void
174Prolog_raise_exception(Prolog_term_ref t) {
175  SP_raise_exception(t);
176}
177
178/*!
179  Return true if \p t is a Prolog variable, false otherwise.
180*/
181PCFLI_EXTERN_INLINE int
182Prolog_is_variable(Prolog_term_ref t) {
183  return SP_is_variable(t);
184}
185
186/*!
187  Return true if \p t is a Prolog atom, false otherwise.
188*/
189PCFLI_EXTERN_INLINE int
190Prolog_is_atom(Prolog_term_ref t) {
191  return SP_is_atom(t);
192}
193
194/*!
195  Return true if \p t is a Prolog integer, false otherwise.
196*/
197PCFLI_EXTERN_INLINE int
198Prolog_is_integer(Prolog_term_ref t) {
199  return SP_is_integer(t);
200}
201
202/*!
203  Return true if \p t is the representation of an address, false otherwise.
204*/
205PCFLI_EXTERN_INLINE int
206Prolog_is_address(Prolog_term_ref t) {
207  return SP_is_integer(t);
208}
209
210/*!
211  Return true if \p t is a Prolog compound term, false otherwise.
212*/
213PCFLI_EXTERN_INLINE int
214Prolog_is_compound(Prolog_term_ref t) {
215  return SP_is_compound(t);
216}
217
218/*!
219  Return true if \p t is a Prolog cons (list constructor), false otherwise.
220*/
221PCFLI_EXTERN_INLINE int
222Prolog_is_cons(Prolog_term_ref t) {
223  return SP_is_list(t);
224}
225
226/*!
227  Assuming \p t is a Prolog integer, return true if its value fits
228  in a long, in which case the value is assigned to \p v,
229  return false otherwise.  The behavior is undefined if \p t is
230  not a Prolog integer.
231*/
232PCFLI_EXTERN_INLINE int
233Prolog_get_long(Prolog_term_ref t, long* lp) {
234  assert(Prolog_is_integer(t));
235  return SP_get_integer(t, lp);
236}
237
238/*!
239  If \p t is the Prolog representation for a memory address, return
240  true and store that address into to \p v; return false otherwise.
241  The behavior is undefined if \p t is not an address.
242*/
243PCFLI_EXTERN_INLINE int
244Prolog_get_address(Prolog_term_ref t, void** vpp) {
245  assert(Prolog_is_address(t));
246  return SP_get_address(t, vpp);
247}
248
249/*!
250  If \p t is a Prolog atom, return true and store its name into \p name.
251  The behavior is undefined if \p t is not a Prolog atom.
252*/
253PCFLI_EXTERN_INLINE int
254Prolog_get_atom_name(Prolog_term_ref t, Prolog_atom* ap) {
255  assert(Prolog_is_atom(t));
256  return SP_get_atom(t, ap);
257}
258
259/*!
260  If \p t is a Prolog compound term, return true and store its name
261  and arity into \p name and \p arity, respectively.
262  The behavior is undefined if \p t is not a Prolog compound term.
263*/
264PCFLI_EXTERN_INLINE int
265Prolog_get_compound_name_arity(Prolog_term_ref t, Prolog_atom* ap, int* ip) {
266  assert(Prolog_is_compound(t));
267  return SP_get_functor(t, ap, ip);
268}
269
270/*!
271  If \p t is a Prolog compound term and \p i is a positive integer
272  less than or equal to its arity, return true and assign to \p a the
273  i-th (principal) argument of \p t.
274  The behavior is undefined if \p t is not a Prolog compound term.
275*/
276PCFLI_EXTERN_INLINE int
277Prolog_get_arg(int i, Prolog_term_ref t, Prolog_term_ref a) {
278  assert(Prolog_is_compound(t));
279  return SP_get_arg(i, t, a);
280}
281
282/*!
283  If \p c is a Prolog cons (list constructor), assign its head and
284  tail to \p h and \p t, respectively.
285  The behavior is undefined if \p c is not a Prolog cons.
286*/
287PCFLI_EXTERN_INLINE int
288Prolog_get_cons(Prolog_term_ref c, Prolog_term_ref h, Prolog_term_ref t) {
289  assert(Prolog_is_cons(c));
290  return SP_get_list(c, h, t);
291}
292
293/*!
294  Unify the terms referenced by \p t and \p u and return true
295  if the unification is successful; return false otherwise.
296*/
297PCFLI_EXTERN_INLINE int
298Prolog_unify(Prolog_term_ref t, Prolog_term_ref u) {
299  return SP_unify(t, u);
300}
301