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)
4 [![Build Status](https://travis-ci.org/m6w6/ext-psi.svg?branch=master)](https://travis-ci.org/m6w6/ext-psi)
6 PSI is a PHP extension, which provides a foreign function interface through
7 `libffi` and/or `libjit`.
9 The acronym PSI may be read as:
10 * PHP System Interface
11 * POSIX Standard Interface
13 The latter because PSI can be configured to include declarations for most of the
14 [base definitions and system interfaces of POSIX.1-2008](http://pubs.opengroup.org/onlinepubs/9699919799/).
17 > This is heavy WIP. Only a small part of configuration and implementation has been completed yet.
21 * standard scalar types mapped to stdint types
22 * structs, unions, enums and typedefs
23 * simple numeric expressions
24 * string and int constants
30 > This is heavy WIP. Installation only works from a source checkout yet.
34 This extension is distributed through [PECL](http://pecl.php.net) and can be
35 installed with [PEAR](http://pear.php.net)'s pecl command:
41 Watch out for [PECL replicates](https://replicator.pharext.org?psi)
42 and [pharext](https://github.com/pharext) packages attached to
43 [releases](https://github.com/m6w6/ext-psi/releases).
47 This extension is hosted at [Github](https://github.com/m6w6/ext-psi) with a
48 personal [mirror](https://git.m6w6.name/?p=m6w6/ext-psi) available.
50 git clone github.com:m6w6/ext-psi
55 ./configure --with-php-config=/path/to/php-config
59 ## Configuring PSI at build time
61 PSI supports the following configure switches:
64 **Enable PHP System Interface support.**
66 This is only relevant for an in-tree build. Use `--enable-psi` to include
67 the PSI extension in the build.
69 ### --enable-psi-posix
70 **Pre-define POSIX decls.**
72 Use `--enable-psi-posix=all` to enable all available POSIX checks.
74 Use `--enable-psi-posix=section,another,onemore` to enable specific modules only.
76 The following modules are included by default:
78 [stdint](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdint.h.html),
79 [stddef](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stddef.h.html),
80 [stdlib](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdlib.h.html),
81 [sys/types](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html)
83 The following modules are available to select:
85 [errno](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html),
86 [fcntl](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fcntl.h.html),
87 [glob](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/glob.h.html),
88 [locale](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/locale.h.html),
89 [ndbm](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/ndbm.h.html),
90 [netdb](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netdb.h.html),
91 [netinet/in](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html),
92 [netinet/tcp](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html),
93 [poll](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/poll.h.html),
94 [signal](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html),
95 [stdio](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdio.h.html),
96 [sys/select](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_select.h.html),
97 [sys/socket](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html),
98 [sys/stat](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html),
99 [sys/time](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_time.h.html),
100 [sys/times](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_times.h.html),
101 [sys/uio](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_uio.h.html),
102 [sys/utsname](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_utsname.h.html),
103 [syslog](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/syslog.h.html),
104 [time](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html),
105 [unistd](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html),
106 [wchar](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/wchar.h.html),
107 [wctype](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/wctype.h.html),
109 ### --with-psi-libjit
113 > We currently rely on a patched libjit, because of an apparent bug in how
114 > libjit creates closures, which still needs to be verified, though.
115 > See https://github.com/m6w6/libjit for the preliminary patch.
117 ### --with-psi-libffi
120 ## Configuring PSI at runtime
124 The backend that PSI should use as FFI, either _jit_ for `libjit` or _ffi_ for `libffi`. Defaults to "ffi".
128 A colon separated list of directories to scan for `*.psi` files. Defaults to "psi.d".
134 * C style multi line comments
135 * C++ style single line comments
138 // this is a one line comment
148 typedef unsigned char xmlChar;
151 They follow the basic C-style `typedef` syntax.
159 You can also `typedef` unions and enums that way.
163 The following example results in exactly the same interpretation as the previous:
166 typedef struct str str_t;
173 A struct will have the size of all its elements plus padding combined and an
174 alignment equal to that of the largest element's alignment.
178 Enums are considered to be of type `int`.
187 Enums will be registered as userland constants with the following pattern:
189 * `psi\STATUS\FAILURE` with value -1
190 * `psi\STATUS\SUCCESS` with value 0
206 Unions will have the size and alignment of the largest element they contain.
214 These statements define what library should be `dlopen()`-ed to look up symbols from declarations.
215 They must only occur once in a file. When a `lib` statement is omitted, stdlib is assumed.
219 Declarations provide all information needed to make a foreign function call.
222 extern char *strerror(int errnum);
225 You may specify a non-standard calling convention in place of `extern`, where `default` and `cdecl` have the same meaning as `extern`.
227 Additionally recognized calling conventions include: `stdcall` and `fastcall`.
232 const int num\ZERO = 0;
233 const string pwd\TOKEN = "4WlOjXGL";
236 Constants must have a namespaced identifiers and are registered as userland constants.
240 Implementations are the userland visible interfaces to the foreign function interface.
243 function str\error(int $num) : string {
244 let errnum = intval($num);
245 return to_string(strerror);
249 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.
254 // all declarations in this file should be looked up in libidn
258 const int \IDNA_SUCCESS = 0;
259 const int \IDNA_STRINGPREP_ERROR = 1;
260 const int \IDNA_PUNYCODE_ERROR = 2;
261 const int \IDNA_CONTAINS_NON_LDH = 3;
262 const int \IDNA_CONTAINS_LDH = 3;
263 const int \IDNA_CONTAINS_MINUS = 4;
264 const int \IDNA_INVALID_LENGTH = 5;
265 const int \IDNA_NO_ACE_PREFIX = 6;
266 const int \IDNA_ROUNDTRIP_VERIFY_ERROR = 7;
267 const int \IDNA_CONTAINS_ACE_PREFIX = 8;
268 const int \IDNA_ICONV_ERROR = 9;
269 const int \IDNA_MALLOC_ERROR = 201;
270 const int \IDNA_DLOPEN_ERROR = 202;
272 const int \IDNA_ALLOW_UNASSIGNED = 1;
273 const int \IDNA_USE_STD3_ASCII_RULES = 2;
275 // nothing special about the declaration here
276 default int idna_to_ascii_8z(char *host, char **buffer, int flags);
278 function idn\utf8_to_ascii(string $host, string &$result, int $flags = 0) : int {
279 // there must be a `let` statement for each
280 // declared argument of the called function
282 // setup a pointer to NULL
285 // setup a string pointer to $host
286 let host = strval($host);
288 // assing the integer value of $flags
289 let flags = intval($flags);
291 // the function to call is referenced in
292 // the return statement, along with the
293 // neccessary cast how to interpred the
294 // returned native value
295 return to_int(idna_to_ascii_8z);
297 // by-ref vars might receive output values
298 // through `set` statments, which also
299 // require a cast how to marshal the
300 // native data as PHP value
301 set $result = to_string(*buffer);
303 // after the buffer has been marshaled
304 // for the PHP engine, we have to free
305 // the buffer to avoid a memory leak
307 // note that in this example we omit the
308 // declaration of the free() function called
309 // in our `free` statement for brevity
312 default char *idna_strerror(int rc);
313 function idn\strerror(int $rc) : string {
314 return to_string(idna_strerror);
315 let rc = intval($rc);
322 $rc = idn\utf8_to_ascii("flöte.de", $result);
323 printf("<%s>\n", $result);
324 printf("%s\n", idn\strerror($rc));
326 $rc = idn\utf8_to_ascii("…asdf….de", $result, IDNA_USE_STD3_ASCII_RULES);
327 printf("<%s>\n", $result);
328 printf("%s\n", idn\strerror($rc));
336 Non-digit/letter/hyphen in input
341 A comprehensive list of changes can be obtained from the
342 [PECL website](https://pecl.php.net/package-changelog.php?package=psi).
344 Known issues are listed in [BUGS](./BUGS) and future ideas can be found in [TODO](./TODO).
348 ext-psi is licensed under the 2-Clause-BSD license, which can be found in
349 the accompanying [LICENSE](./LICENSE) file.
353 All forms of contribution are welcome! Please see the bundled
354 [CONTRIBUTING](./CONTRIBUTING.md) note for the general principles followed.
356 The list of past and current contributors is maintained in [THANKS](./THANKS).