File: pl-builtin.h

package info (click to toggle)
swi-prolog 6.6.6-1~bpo70+1
  • links: PTS, VCS
  • area: main
  • in suites: wheezy-backports
  • size: 82,312 kB
  • sloc: ansic: 322,250; perl: 245,822; sh: 6,651; java: 5,254; makefile: 4,423; cpp: 4,153; ruby: 1,594; yacc: 843; xml: 82; sed: 12; sql: 6
file content (330 lines) | stat: -rw-r--r-- 10,680 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
/*  $Id$

    Part of SWI-Prolog

    Author:        Jan Wielemaker
    E-mail:        J.Wielemaker@uva.nl
    WWW:           http://www.swi-prolog.org
    Copyright (C): 1985-2008, University of Amsterdam

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef PL_BUILTIN_H_INCLUDED
#define PL_BUILTIN_H_INCLUDED

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
This header provides definition that allow us compiling the C files that
define built-in predicates, disclosing as little   as  possible from the
SWI-Prolog kernel. The aim of this seperate   module is to allow reusing
these files in other Prolog systems with  minimal effort by providing an
implementation of this macro layer  that   satisfies  the  target Prolog
system.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

		 /*******************************
		 *	   COMMON GROUND	*
		 *******************************/

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
First, include config.h or, if MD is  specified, this file.  This allows
for -DMD="config/win64.h"
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

#if defined(O_PLMT) && !defined(_REENTRANT)
#define _REENTRANT 1
#endif

#if HAVE_XOS_H
#include <xos.h>			/* Windows POSIX enhancements */
#endif
#ifdef HAVE_UXNT_H
#include "os/windows/uxnt.h"		/* More Windows POSIX enhancements */
#endif

#include "pl-mutex.h"
#include "os/SWI-Stream.h"

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Symbols are local to shared objects  by   default  in  COFF based binary
formats, and public in ELF based formats.   In some ELF based systems it
is possible to make them local   anyway. This enhances encapsulation and
avoids an indirection for calling these   functions.  Functions that are
supposed to be local to the SWI-Prolog kernel are declared using

    COMMON(<type) <function>(<args>);
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

#ifdef HAVE_VISIBILITY_ATTRIBUTE
#define SO_LOCAL __attribute__((visibility("hidden")))
#else
#define SO_LOCAL
#endif
#define COMMON(type) SO_LOCAL type


		 /*******************************
		 *	    ENGINE ACCESS	*
		 *******************************/

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
The  engine  is  a  structure  that  is    represented  by  LD.  On  the
single-engine version this is simply the  address of a global structure.
On the multi-threaded version we must use some thread-specific mechanism
to find the engine structure  associated   with  the current thread. The
user of this module must provide two   definitions:

	* struct PL_local_data
	Structure definition for the engine
	* LD_GLOBAL
	Is a macro that expands to a pointer to the current engine.  The
	implementation varies.  Without engines it is just an alias for
	the address of the global engine structure.  With engines, it
	can use pthread_getspecific() (POSIX), TlsGetValue (Windows) or
	some compiler provided extension for thread-local variables.

LD always points to the  engine,  but   retrieving  it  everywhere  in a
function can be costly. GET_LD and  PRED_LD create an automatic variable
__PL_ld pointing to the engine.  LOCAL_LD   points  there. Time critical
modules generally start with:

#undef LD
#define LD LOCAL_LD

Now, functions that access LD must be written as:

func()
{ GET_LD

  ...
}

And predicates as

static
PRED_IMPL("foo", 2, foo, 0)
{ PRED_LD

   ...
}

In addition, LD can be passed between functions.  This is written as

func1(int arg ARG_LD)
{ ...
}

  func1(42 PASS_LD)

Note there is *NO* "," before ARG_LD   and PASS_LD, because these macros
expand to nothing if there is just  one engine. The versions ARG1_LD and
PASS_LD1 are used if there is no other argument.

On some frequently used functions,   writing PASS_LD everywhere clutters
the code too much. In this case  we   use  the schema below. Many of the
time critical functions from the public   foreign  interface are handled
this way for the internal builtins.

func__LD(int arg ARG_LD)
{ ...
}

#define func(arg) func__LD(arg PASS_LD)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

typedef struct PL_local_data  PL_local_data_t;
typedef struct PL_global_data PL_global_data_t;

#define LD	  GLOBAL_LD

#if defined(O_PLMT) || defined(O_MULTIPLE_ENGINES)

#define GET_LD	  PL_local_data_t *__PL_ld = GLOBAL_LD;
#define PRED_LD   PL_local_data_t *__PL_ld = PL__ctx->engine;

#define ARG1_LD   PL_local_data_t *__PL_ld
#define ARG_LD    , ARG1_LD
#define PASS_LD1  LD
#define PASS_LD   , LD
#define LOCAL_LD  __PL_ld
#define IGNORE_LD (void)__PL_ld;

#else

#define GET_LD
#define ARG_LD
#define ARG1_LD void
#define PASS_LD
#define PASS_LD1
#define LOCAL_LD  (&PL_local_data)
#define GLOBAL_LD (&PL_local_data)
#define LD	  GLOBAL_LD
#define IGNORE_LD

#endif


		 /*******************************
		 *	 PRINT DEBUG INFO	*
		 *******************************/

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Internal debugging  and extra security checks.   To  enable them, compile
with -DO_DEBUG. Information should be printed using Sdprintf, which takes
the same arguments as printf(). Using Sdprintf() ensures that information
is also printed if stdio is not available.

    DEBUG(1, Sdprintf("Running with pid=%d\n", getpid()));
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

#include "pl-debug.h"

#if O_DEBUG
#define DEBUG(n, g) do { if ((n <= DBG_LEVEL9 && GD->debug_level >= (n)) || \
                             (n > DBG_LEVEL9 && GD->debug_topics && \
                              true_bit(GD->debug_topics, n))) \
                         { g; } } while(0)
#define DEBUGGING(n) (GD->debug_topics && true_bit(GD->debug_topics, n))
#else
#define DEBUG(a, b) ((void)0)
#endif

#if O_SECURE
#define SECURE(g) do { g; } while(0)
#else
#define SECURE(g) ((void)0)
#endif


		 /*******************************
		 *   NON-DET PREDICATE CONTEXT	*
		 *******************************/

typedef enum
{ FRG_FIRST_CALL = 0,		/* Initial call */
  FRG_CUTTED     = 1,		/* Context was cutted */
  FRG_REDO	 = 2		/* Normal redo */
} frg_code;

typedef struct foreign_context
{ uintptr_t		context;	/* context value */
  frg_code		control;	/* FRG_* action */
  struct PL_local_data *engine;		/* invoking engine */
} *control_t;

#define FRG_REDO_MASK	0x03
#define FRG_REDO_BITS	2
#define REDO_INT	0x02		/* Returned an integer */
#define REDO_PTR	0x03		/* returned a pointer */

#define ForeignRedoIntVal(v)	(((uintptr_t)(v)<<FRG_REDO_BITS)|REDO_INT)
#define ForeignRedoPtrVal(v)	(((uintptr_t)(v))|REDO_PTR)

#define ForeignRedoInt(v)	return ForeignRedoIntVal(v)
#define ForeignRedoPtr(v)	return ForeignRedoPtrVal(v)

#define ForeignControl(h)	((h)->control)
#define ForeignContextInt(h)	((intptr_t)(h)->context)
#define ForeignContextPtr(h)	((void *)(h)->context)
#define ForeignEngine(h)	((h)->engine)


		 /*******************************
		 *	   BIND PREDICATES	*
		 *******************************/

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Built-in predicates are defined as

PRED_IMPL("name", arity, c_symbol, flags)
{ <implementation body>
}

The macros A1..A10 provide access to the arguments (of type term_t). The
CTX_*  macros  provide  the  actual  arity  and  context  arguments  for
non-deterministic predicates. The implementation returns   using  one of
these  constructs.  The  `Redo'   variations    are   only   allowed  if
PL_FA_NONDETERMINISTIC is present in `flags'.

    * return FALSE
    * return TRUE
    * ForeignRedoInt(intptr_t val)
    * ForeignRedoPtr(void *ptr)

At the end of the file there is   a  section that looks like this, where
each PRED_DEF line  is  a  simple   direct  copy  of  the  corresponding
PRED_IMPL declaration:

BeginPredDefs(module)
  PRED_DEF("name", arity, c_symbol, flags)
  ...
EndPredDefs
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

#define PRED_IMPL(name, arity, fname, flags) \
        foreign_t \
        pl_ ## fname ## arity ## _va(term_t PL__t0, int PL__ac, \
				     control_t PL__ctx)

#define Arg(N)  (PL__t0+((n)-1))
#define A1      (PL__t0)
#define A2      (PL__t0+1)
#define A3      (PL__t0+2)
#define A3      (PL__t0+2)
#define A4      (PL__t0+3)
#define A5      (PL__t0+4)
#define A6      (PL__t0+5)
#define A7      (PL__t0+6)
#define A8      (PL__t0+7)
#define A9      (PL__t0+8)
#define A10     (PL__t0+9)

#define CTX_CNTRL ForeignControl(PL__ctx)
#define CTX_PTR   ForeignContextPtr(PL__ctx)
#define CTX_INT   ForeignContextInt(PL__ctx)
#define CTX_ARITY PL__ac

#define BeginPredDefs(id) \
        const PL_extension PL_predicates_from_ ## id[] = {
#define PRED_DEF(name, arity, fname, flags) \
        { name, arity, pl_ ## fname ## arity ## _va, (flags)|PL_FA_VARARGS },
#define PRED_SHARE(name, arity, fname, flags) \
        { name, arity, pl_ ## fname ## va_va, (flags)|PL_FA_VARARGS },
#define EndPredDefs \
        { NULL, 0, NULL, 0 } \
        };

		 /*******************************
		 *	       TIME		*
		 *******************************/

#define PL_unify_time(t, s) PL_unify_float(t, (double)(s))


		 /*******************************
		 *	       MISC		*
		 *******************************/

/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
blockGC() and unblockGC() control  garbage   collection  in the provided
engine. The calls can be  nested,  but   the  program  must  ensure each
blockGC() is matched by an unblockGC().
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */

COMMON(void)	blockGC(int flags ARG_LD);	/* disallow garbage collect */
COMMON(void)	unblockGC(int flags ARG_LD);	/* re-allow garbage collect */
COMMON(void)	suspendTrace(int suspend);	/* suspend/resume tracing */

#endif /*PL_BUILTIN_H_INCLUDED*/