3 [![Build Status](https://travis-ci.org/m6w6/ext-psi.svg?branch=master)](https://travis-ci.org/m6w6/ext-psi)
5 PSI is a PHP extension, which provides a foreign function interface through
6 `libffi` and/or `libjit`.
8 The acronym PSI may be read as:
10 * POSIX Standard Interface
12 The latter because PSI can be configured to include declarations for most of the
13 [base definitions and system interfaces of POSIX.1-2008](http://pubs.opengroup.org/onlinepubs/9699919799/).
16 > This is heavy WIP. Only a small part of configuration and implementation has been completed yet.
20 * standard scalar types mapped to stdint types
21 * structs, unions, enums and typedefs
22 * simple numeric expressions
23 * string and int constants
29 > This is heavy WIP. Installation only works from a source checkout yet.
33 This extension is distributed through [PECL](http://pecl.php.net) and can be
34 installed with [PEAR](http://pear.php.net)'s pecl command:
40 Watch out for [PECL replicates](https://replicator.pharext.org?psi)
41 and [pharext](https://github.com/pharext) packages attached to
42 [releases](https://github.com/m6w6/ext-psi/releases).
46 This extension is hosted at [Github](https://github.com/m6w6/ext-psi) with a
47 personal [mirror](https://git.m6w6.name/?p=m6w6/ext-psi) available.
49 git clone github.com:m6w6/ext-psi
54 ./configure --with-php-config=/path/to/php-config
58 ## Configuring PSI at build time
60 PSI supports the following configure switches:
63 **Enable PHP System Interface support.**
65 This is only relevant for an in-tree build. Use `--enable-psi` to include
66 the PSI extension in the build.
68 ### --enable-psi-posix
69 **Pre-define POSIX decls.**
71 Use `--enable-psi-posix=all` to enable all available POSIX checks.
73 Use `--enable-psi-posix=section,another,onemore` to enable specific modules only.
75 The following modules are included by default:
77 [stdint](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdint.h.html),
78 [stddef](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stddef.h.html),
79 [stdlib](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdlib.h.html),
80 [sys/types](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html)
82 The following modules are available to select:
84 [errno](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html),
85 [fcntl](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fcntl.h.html),
86 [glob](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/glob.h.html),
87 [locale](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/locale.h.html),
88 [ndbm](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/ndbm.h.html),
89 [netdb](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netdb.h.html),
90 [netinet/in](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html),
91 [netinet/tcp](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html),
92 [poll](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/poll.h.html),
93 [signal](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html),
94 [stdio](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdio.h.html),
95 [sys/select](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_select.h.html),
96 [sys/socket](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html),
97 [sys/stat](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html),
98 [sys/time](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_time.h.html),
99 [sys/times](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_times.h.html),
100 [sys/uio](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_uio.h.html),
101 [sys/utsname](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_utsname.h.html),
102 [syslog](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/syslog.h.html),
103 [time](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html),
104 [unistd](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html),
105 [wchar](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/wchar.h.html),
106 [wctype](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/wctype.h.html),
108 ### --with-psi-libjit
112 > We currently rely on a patched libjit, because of an apparent bug in how
113 > libjit creates closures, which still needs to be verified, though.
114 > See https://github.com/m6w6/libjit for the preliminary patch.
116 ### --with-psi-libffi
119 ## Configuring PSI at runtime
123 The backend that PSI should use as FFI, either _jit_ for `libjit` or _ffi_ for `libffi`. Defaults to "ffi".
127 A colon separated list of directories to scan for `*.psi` files. Defaults to "psi.d".
133 * C style multi line comments
134 * C++ style single line comments
135 * CPP directives are ignored, so the hash sign basically works as single line comment
138 // this is a one line comment
143 # this looks like a pre-processor directive and is ignored
149 typedef unsigned char xmlChar;
152 They follow the basic C-style `typedef` syntax.
160 You can also `typedef` unions and enums that way.
164 The following example results in exactly the same interpretation as the previous:
167 typedef struct str str_t;
174 A struct will have the size of all its elements plus padding combined and an
175 alignment equal to that of the largest element's alignment.
179 Enums are considered to be of type `int`.
188 Enums will be registered as userland constants with the following pattern:
190 * `psi\STATUS\FAILURE` with value -1
191 * `psi\STATUS\SUCCESS` with value 0
207 Unions will have the size and alignment of the largest element they contain.
215 These statements define what library should be `dlopen()`-ed to look up symbols from declarations.
216 They must only occur once in a file. When a `lib` statement is omitted, stdlib is assumed.
220 Declarations provide all information needed to make a foreign function call.
223 extern char *strerror(int errnum);
226 You may specify a non-standard calling convention in place of `extern`, where `default` and `cdecl` have the same meaning as `extern`.
228 Additionally recognized calling conventions include: `mscdecl`, `stdcall` and `fastcall`.
233 const int num\ZERO = 0;
234 const string pwd\TOKEN = "4WlOjXGL";
237 Constants must have a namespaced identifiers and are registered as userland constants.
241 Implementations are the userland visible interfaces to the foreign function interface.
244 function str\error(int $num) : string {
245 let errnum = intval($num);
246 return to_string(strerror);
250 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.
255 # all declarations in this file should be looked up in libidn
259 const int \IDNA_SUCCESS = 0;
260 const int \IDNA_STRINGPREP_ERROR = 1;
261 const int \IDNA_PUNYCODE_ERROR = 2;
262 const int \IDNA_CONTAINS_NON_LDH = 3;
263 const int \IDNA_CONTAINS_LDH = 3;
264 const int \IDNA_CONTAINS_MINUS = 4;
265 const int \IDNA_INVALID_LENGTH = 5;
266 const int \IDNA_NO_ACE_PREFIX = 6;
267 const int \IDNA_ROUNDTRIP_VERIFY_ERROR = 7;
268 const int \IDNA_CONTAINS_ACE_PREFIX = 8;
269 const int \IDNA_ICONV_ERROR = 9;
270 const int \IDNA_MALLOC_ERROR = 201;
271 const int \IDNA_DLOPEN_ERROR = 202;
273 const int \IDNA_ALLOW_UNASSIGNED = 1;
274 const int \IDNA_USE_STD3_ASCII_RULES = 2;
276 # nothing special about the declaration here
277 default int idna_to_ascii_8z(char *host, char **buffer, int flags);
279 function idn\utf8_to_ascii(string $host, string &$result, int $flags = 0) : int {
280 # there must be a `let` statement for each
281 # declared argument of the called function
283 # setup a pointer to NULL
286 # setup a string pointer to $host
287 let host = strval($host);
289 # assing the integer value of $flags
290 let flags = intval($flags);
292 # the function to call is referenced in
293 # the return statement, along with the
294 # neccessary cast how to interpred the
295 # returned native value
296 return to_int(idna_to_ascii_8z);
298 # by-ref vars might receive output values
299 # through `set` statments, which also
300 # require a cast how to marshal the
301 # native data as PHP value
302 set $result = to_string(*buffer);
304 # after the buffer has been marshaled
305 # for the PHP engine, we have to free
306 # the buffer to avoid a memory leak
308 # note that in this example we omit the
309 # declaration of the free() function called
310 # in our `free` statement for brevity
313 default char *idna_strerror(int rc);
314 function idn\strerror(int $rc) : string {
315 return to_string(idna_strerror);
316 let rc = intval($rc);
323 $rc = idn\utf8_to_ascii("flöte.de", $result);
324 printf("<%s>\n", $result);
325 printf("%s\n", idn\strerror($rc));
327 $rc = idn\utf8_to_ascii("…asdf….de", $result, IDNA_USE_STD3_ASCII_RULES);
328 printf("<%s>\n", $result);
329 printf("%s\n", idn\strerror($rc));
337 Non-digit/letter/hyphen in input
342 A comprehensive list of changes can be obtained from the
343 [PECL website](https://pecl.php.net/package-changelog.php?package=psi).
345 Known issues are listed in [BUGS](./BUGS) and future ideas can be found in [TODO](./TODO).
349 ext-psi is licensed under the 2-Clause-BSD license, which can be found in
350 the accompanying [LICENSE](./LICENSE) file.
354 All forms of contribution are welcome! Please see the bundled
355 [CONTRIBUTING](./CONTRIBUTING.md) note for the general principles followed.
357 The list of past and current contributors is maintained in [THANKS](./THANKS).