3 [![Join the chat at https://gitter.im/m6w6/ext-psi](https://badges.gitter.im/m6w6/ext-psi.svg)](https://gitter.im/m6w6/ext-psi?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
5 [![Build Status](https://travis-ci.org/m6w6/ext-psi.svg?branch=master)](https://travis-ci.org/m6w6/ext-psi)
7 PSI is a PHP extension, which provides a foreign function interface through
8 `libffi` and/or `libjit`.
10 The acronym PSI may be read as:
11 * PHP System Interface
12 * POSIX Standard Interface
14 The latter because PSI can be configured to include declarations for most of the
15 [base definitions and system interfaces of POSIX.1-2008](http://pubs.opengroup.org/onlinepubs/9699919799/).
18 > This is heavy WIP. Only a small part of configuration and implementation has been completed yet.
22 * standard scalar types mapped to stdint types
23 * structs, unions, enums and typedefs
24 * simple numeric expressions
25 * string and int constants
31 > This is heavy WIP. Installation only works from a source checkout yet.
35 This extension is distributed through [PECL](http://pecl.php.net) and can be
36 installed with [PEAR](http://pear.php.net)'s pecl command:
42 Watch out for [PECL replicates](https://replicator.pharext.org?psi)
43 and [pharext](https://github.com/pharext) packages attached to
44 [releases](https://github.com/m6w6/ext-psi/releases).
48 This extension is hosted at [Github](https://github.com/m6w6/ext-psi) with a
49 personal [mirror](https://git.m6w6.name/?p=m6w6/ext-psi) available.
51 git clone github.com:m6w6/ext-psi
56 ./configure --with-php-config=/path/to/php-config
60 ## Configuring PSI at build time
62 PSI supports the following configure switches:
65 **Enable PHP System Interface support.**
67 This is only relevant for an in-tree build. Use `--enable-psi` to include
68 the PSI extension in the build.
70 ### --enable-psi-posix
71 **Pre-define POSIX decls.**
73 Use `--enable-psi-posix=all` to enable all available POSIX checks.
75 Use `--enable-psi-posix=section,another,onemore` to enable specific modules only.
77 The following modules are included by default:
79 [stdint](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdint.h.html),
80 [stddef](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stddef.h.html),
81 [stdlib](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdlib.h.html),
82 [sys/types](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html)
84 The following modules are available to select:
86 [errno](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html),
87 [fcntl](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fcntl.h.html),
88 [glob](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/glob.h.html),
89 [locale](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/locale.h.html),
90 [ndbm](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/ndbm.h.html),
91 [netdb](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netdb.h.html),
92 [netinet/in](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html),
93 [netinet/tcp](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html),
94 [poll](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/poll.h.html),
95 [signal](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html),
96 [stdio](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdio.h.html),
97 [sys/select](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_select.h.html),
98 [sys/socket](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html),
99 [sys/stat](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html),
100 [sys/time](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_time.h.html),
101 [sys/times](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_times.h.html),
102 [sys/uio](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_uio.h.html),
103 [sys/utsname](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_utsname.h.html),
104 [syslog](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/syslog.h.html),
105 [time](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html),
106 [unistd](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html),
107 [wchar](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/wchar.h.html),
108 [wctype](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/wctype.h.html),
110 ### --with-psi-libjit
114 > We currently rely on a patched libjit, because of an apparent bug in how
115 > libjit creates closures, which still needs to be verified, though.
116 > See https://github.com/m6w6/libjit for the preliminary patch.
118 ### --with-psi-libffi
121 ## Configuring PSI at runtime
125 The backend that PSI should use as FFI, either _jit_ for `libjit` or _ffi_ for `libffi`. Defaults to "ffi".
129 A colon separated list of directories to scan for `*.psi` files. Defaults to "psi.d".
135 * C style multi line comments
136 * C++ style single line comments
137 * CPP directives are ignored, so the hash sign basically works as single line comment
140 // this is a one line comment
145 # this looks like a pre-processor directive and is ignored
151 typedef unsigned char xmlChar;
154 They follow the basic C-style `typedef` syntax.
162 You can also `typedef` unions and enums that way.
166 The following example results in exactly the same interpretation as the previous:
169 typedef struct str str_t;
176 A struct will have the size of all its elements plus padding combined and an
177 alignment equal to that of the largest element's alignment.
181 Enums are considered to be of type `int`.
190 Enums will be registered as userland constants with the following pattern:
192 * `psi\STATUS\FAILURE` with value -1
193 * `psi\STATUS\SUCCESS` with value 0
209 Unions will have the size and alignment of the largest element they contain.
217 These statements define what library should be `dlopen()`-ed to look up symbols from declarations.
218 They must only occur once in a file. When a `lib` statement is omitted, stdlib is assumed.
222 Declarations provide all information needed to make a foreign function call.
225 extern char *strerror(int errnum);
228 You may specify a non-standard calling convention in place of `extern`, where `default` and `cdecl` have the same meaning as `extern`.
230 Additionally recognized calling conventions include: `stdcall` and `fastcall`.
235 const int num\ZERO = 0;
236 const string pwd\TOKEN = "4WlOjXGL";
239 Constants must have a namespaced identifiers and are registered as userland constants.
243 Implementations are the userland visible interfaces to the foreign function interface.
246 function str\error(int $num) : string {
247 let errnum = intval($num);
248 return to_string(strerror);
252 Each implementation refers to exactly one declared foreign function referenced in its `return` statement. Each declaration, on the other hand, may have any number of implementations.
257 # all declarations in this file should be looked up in libidn
261 const int \IDNA_SUCCESS = 0;
262 const int \IDNA_STRINGPREP_ERROR = 1;
263 const int \IDNA_PUNYCODE_ERROR = 2;
264 const int \IDNA_CONTAINS_NON_LDH = 3;
265 const int \IDNA_CONTAINS_LDH = 3;
266 const int \IDNA_CONTAINS_MINUS = 4;
267 const int \IDNA_INVALID_LENGTH = 5;
268 const int \IDNA_NO_ACE_PREFIX = 6;
269 const int \IDNA_ROUNDTRIP_VERIFY_ERROR = 7;
270 const int \IDNA_CONTAINS_ACE_PREFIX = 8;
271 const int \IDNA_ICONV_ERROR = 9;
272 const int \IDNA_MALLOC_ERROR = 201;
273 const int \IDNA_DLOPEN_ERROR = 202;
275 const int \IDNA_ALLOW_UNASSIGNED = 1;
276 const int \IDNA_USE_STD3_ASCII_RULES = 2;
278 # nothing special about the declaration here
279 default int idna_to_ascii_8z(char *host, char **buffer, int flags);
281 function idn\utf8_to_ascii(string $host, string &$result, int $flags = 0) : int {
282 # there must be a `let` statement for each
283 # declared argument of the called function
285 # setup a pointer to NULL
288 # setup a string pointer to $host
289 let host = strval($host);
291 # assing the integer value of $flags
292 let flags = intval($flags);
294 # the function to call is referenced in
295 # the return statement, along with the
296 # neccessary cast how to interpred the
297 # returned native value
298 return to_int(idna_to_ascii_8z);
300 # by-ref vars might receive output values
301 # through `set` statments, which also
302 # require a cast how to marshal the
303 # native data as PHP value
304 set $result = to_string(*buffer);
306 # after the buffer has been marshaled
307 # for the PHP engine, we have to free
308 # the buffer to avoid a memory leak
310 # note that in this example we omit the
311 # declaration of the free() function called
312 # in our `free` statement for brevity
315 default char *idna_strerror(int rc);
316 function idn\strerror(int $rc) : string {
317 return to_string(idna_strerror);
318 let rc = intval($rc);
325 $rc = idn\utf8_to_ascii("flöte.de", $result);
326 printf("<%s>\n", $result);
327 printf("%s\n", idn\strerror($rc));
329 $rc = idn\utf8_to_ascii("…asdf….de", $result, IDNA_USE_STD3_ASCII_RULES);
330 printf("<%s>\n", $result);
331 printf("%s\n", idn\strerror($rc));
339 Non-digit/letter/hyphen in input
344 A comprehensive list of changes can be obtained from the
345 [PECL website](https://pecl.php.net/package-changelog.php?package=psi).
347 Known issues are listed in [BUGS](./BUGS) and future ideas can be found in [TODO](./TODO).
351 ext-psi is licensed under the 2-Clause-BSD license, which can be found in
352 the accompanying [LICENSE](./LICENSE) file.
356 All forms of contribution are welcome! Please see the bundled
357 [CONTRIBUTING](./CONTRIBUTING.md) note for the general principles followed.
359 The list of past and current contributors is maintained in [THANKS](./THANKS).