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/).
17 * standard scalar types mapped to stdint types
18 * structs, unions, enums and typedefs
19 * simple numeric expressions
20 * string and int constants
27 This extension is distributed through [PECL](http://pecl.php.net) and can be
28 installed with [PEAR](http://pear.php.net)'s pecl command:
34 Watch out for [PECL replicates](https://replicator.pharext.org?psi)
35 and [pharext](https://github.com/pharext) packages attached to
36 [releases](https://github.com/m6w6/ext-psi/releases).
40 This extension is hosted at [Github](https://github.com/m6w6/ext-psi) with a
41 personal [mirror](https://git.m6w6.name/?p=m6w6/ext-psi) available.
43 git clone github.com:m6w6/ext-psi
48 ./configure --with-php-config=/path/to/php-config
52 ## Configuring PSI at build time
54 PSI supports the following configure switches:
57 **Enable PHP System Interface support.**
59 This is only relevant for an in-tree build. Use `--enable-psi` to include
60 the PSI extension in the build.
62 ### --enable-psi-posix
63 **Pre-define POSIX decls.**
65 Use `--enable-psi-posix=all` to enable all available POSIX checks.
67 Use `--enable-psi-posix=section,another,onemore` to enable specific modules only.
69 The following modules are included by default:
71 [stdint](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdint.h.html),
72 [stddef](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stddef.h.html),
73 [stdlib](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdlib.h.html),
74 [sys/types](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_types.h.html)
76 The following modules are available to select:
78 [errno](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/errno.h.html),
79 [fcntl](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/fcntl.h.html),
80 [glob](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/glob.h.html),
81 [locale](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/locale.h.html),
82 [ndbm](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/ndbm.h.html),
83 [netdb](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netdb.h.html),
84 [netinet/in](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_in.h.html),
85 [netinet/tcp](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netinet_tcp.h.html),
86 [poll](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/poll.h.html),
87 [signal](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html),
88 [stdio](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/stdio.h.html),
89 [sys/select](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_select.h.html),
90 [sys/socket](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_socket.h.html),
91 [sys/stat](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html),
92 [sys/time](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_time.h.html),
93 [sys/times](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_times.h.html),
94 [sys/uio](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_uio.h.html),
95 [sys/utsname](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_utsname.h.html),
96 [syslog](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/syslog.h.html),
97 [time](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/time.h.html),
98 [unistd](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/unistd.h.html),
99 [wchar](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/wchar.h.html),
100 [wctype](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/wctype.h.html),
102 ### --with-psi-libjit
105 ### --with-psi-libffi
108 ## Configuring PSI at runtime
112 The backend that PSI should use as FFI, either _jit_ for `libjit` or _ffi_ for `libffi`. Defaults to "ffi".
116 A colon separated list of directories to scan for `*.psi` files. Defaults to "psi.d".
122 * C style multi line comments
123 * C++ style single line comments
124 * CPP directives are ignored, so the hash sign basically works as single line comment
127 // this is a one line comment
132 # this looks like a pre-processor directive and is ignored
138 typedef unsigned char xmlChar;
141 They follow the basic C-style `typedef` syntax.
149 You can also `typedef` unions and enums that way.
153 The following example results in exactly the same interpretation as the previous:
156 typedef struct str str_t;
163 A struct will have the size of all its elements plus padding combined and an
164 alignment equal to that of the largest element's alignment.
168 Enums are considered to be of type `int`.
177 Enums will be registered as userland constants with the following pattern:
179 * `psi\STATUS\FAILURE` with value -1
180 * `psi\STATUS\SUCCESS` with value 0
196 Unions will have the size and alignment of the largest element they contain.
204 These statements define what library should be `dlopen()`-ed to look up symbols from declarations.
205 They must only occur once in a file. When a `lib` statement is omitted, stdlib is assumed.
209 Declarations provide all information needed to make a foreign function call.
212 extern char *strerror(int errnum);
215 You may specify a non-standard calling convention in place of `extern`, where `default` and `cdecl` have the same meaning as `extern`.
217 Additionally recognized calling conventions include: `mscdecl`, `stdcall` and `fastcall`.
222 const int num\ZERO = 0;
223 const string pwd\TOKEN = "4WlOjXGL";
226 Constants must have a namespaced identifiers and are registered as userland constants.
230 Implementations are the userland visible interfaces to the foreign function interface.
233 function str\error(int $num) : string {
234 let errnum = intval($num);
235 return to_string(strerror);
239 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.
244 # all declarations in this file should be looked up in libidn
248 const int \IDNA_SUCCESS = 0;
249 const int \IDNA_STRINGPREP_ERROR = 1;
250 const int \IDNA_PUNYCODE_ERROR = 2;
251 const int \IDNA_CONTAINS_NON_LDH = 3;
252 const int \IDNA_CONTAINS_LDH = 3;
253 const int \IDNA_CONTAINS_MINUS = 4;
254 const int \IDNA_INVALID_LENGTH = 5;
255 const int \IDNA_NO_ACE_PREFIX = 6;
256 const int \IDNA_ROUNDTRIP_VERIFY_ERROR = 7;
257 const int \IDNA_CONTAINS_ACE_PREFIX = 8;
258 const int \IDNA_ICONV_ERROR = 9;
259 const int \IDNA_MALLOC_ERROR = 201;
260 const int \IDNA_DLOPEN_ERROR = 202;
262 const int \IDNA_ALLOW_UNASSIGNED = 1;
263 const int \IDNA_USE_STD3_ASCII_RULES = 2;
265 # nothing special about the declaration here
266 default int idna_to_ascii_8z(char *host, char **buffer, int flags);
268 function idn\utf8_to_ascii(string $host, string &$result, int $flags = 0) : int {
269 # there must be a `let` statement for each
270 # declared argument of the called function
272 # setup a pointer to NULL
275 # setup a string pointer to $host
276 let host = strval($host);
278 # assing the integer value of $flags
279 let flags = intval($flags);
281 # the function to call is referenced in
282 # the return statement, along with the
283 # neccessary cast how to interpred the
284 # returned native value
285 return to_int(idna_to_ascii_8z);
287 # by-ref vars might receive output values
288 # through `set` statments, which also
289 # require a cast how to marshal the
290 # native data as PHP value
291 set $result = to_string(*buffer);
293 # after the buffer has been marshaled
294 # for the PHP engine, we have to free
295 # the buffer to avoid a memory leak
297 # note that in this example we omit the
298 # declaration of the free() function called
299 # in our `free` statement for brevity
302 default char *idna_strerror(int rc);
303 function idn\strerror(int $rc) : string {
304 return to_string(idna_strerror);
305 let rc = intval($rc);
312 $rc = idn\utf8_to_ascii("flöte.de", $result);
313 printf("<%s>\n", $result);
314 printf("%s\n", idn\strerror($rc));
316 $rc = idn\utf8_to_ascii("…asdf….de", $result, IDNA_USE_STD3_ASCII_RULES);
317 printf("<%s>\n", $result);
318 printf("%s\n", idn\strerror($rc));
326 Non-digit/letter/hyphen in input
331 A comprehensive list of changes can be obtained from the
332 [PECL website](https://pecl.php.net/package-changelog.php?package=psi).
334 Known issues are listed in [BUGS](./BUGS) and future ideas can be found in [TODO](./TODO).
338 ext-psi is licensed under the 2-Clause-BSD license, which can be found in
339 the accompanying [LICENSE](./LICENSE) file.
343 All forms of contribution are welcome! Please see the bundled
344 [CONTRIBUTING](./CONTRIBUTING.md) note for the general principles followed.
346 The list of past and current contributors is maintained in [THANKS](./THANKS).