fix test
[m6w6/ext-psi] / README.md
1 # ext-psi
2
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)
5
6 PSI is a PHP extension, which provides a foreign function interface through
7 `libffi` and/or `libjit`.
8
9 The acronym PSI may be read as:
10 * PHP System Interface
11
12 > **WARNING:**
13 > This is heavy WIP.
14
15 ## Features
16
17 * structs, unions, enums and typedefs
18 * numeric and boolean expressions
19 * scalar constants
20 * vararg calls
21
22 ## Installing
23
24 > **WARNING:**
25 > This is heavy WIP. Installation only works from a source checkout
26 > with php-src@master on x86_64-linux yet.
27 > Sort of works on x64_64-darwin, too, roughly.
28
29 ### PECL
30
31 > Not implemented yet.
32
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:
35
36 pecl install psi
37
38 ### PHARext
39
40 > Not implemented yet.
41
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).
45
46 ### Checkout
47
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.
50
51 git clone github.com:m6w6/ext-psi
52
53 cd ext-psi
54
55 /path/to/phpize
56 ./configure --with-php-config=/path/to/php-config
57 make
58 sudo make install
59
60 ## Configuring PSI at build time
61
62 PSI supports the following configure switches:
63
64 ### --enable-psi
65 **Enable PHP System Interface support.**
66
67 This is only relevant for an in-tree build. Use `--enable-psi` to include
68 the PSI extension in the build.
69
70 ### --with-psi-libjit
71 **Path to libjit.**
72
73 > **WARNING:**
74 > We currently rely on a patched libjit, because of an apparent bug in how
75 > libjit creates closures, which still needs to be verified, though.
76 > See https://github.com/m6w6/libjit for the preliminary patch.
77
78 ### --with-psi-libffi
79 **Path to libffi.**
80
81 ## Configuring PSI at runtime
82
83 ### psi.engine
84
85 The backend that PSI should use as FFI, either _jit_ for `libjit` or _ffi_ for `libffi`. Defaults to "ffi".
86
87 ### psi.directory
88
89 A colon separated list of directories to scan for `*.psi` files. Defaults to "psi.d".
90
91 ### psi.blacklist.decls
92
93 A comma separated list of C function declarations to ignore.
94
95 ### psi.blacklist.vars
96
97 A comma separated list of C variable declarations to ignore.
98
99 ## PSI files
100
101 PSI files are augmented C header files. So, everything usually found in C
102 headers including comments, preprocessor directives, typedefs, structs,
103 unions, enums, function and variable declarations should work.
104
105 That means, that you can just include C headers in the usual way:
106
107 ```c
108 #include <stdlib.h>
109 ```
110
111 ### Dynamic Libraries
112
113 PSI needs to know which library it should `dlopen` unless the declared functions
114 are provided by the standard C library. Therefore the PSI preprocessor
115 understands a special pragma:
116
117 ```c
118 #pragma lib "crypt"
119 ```
120
121 ### Constants
122
123 ```c
124 const int num\ZERO = 0;
125 const string pwd\TOKEN = "4WlOjXGL";
126 ```
127
128 Constants must have namespaced identifiers and are registered as userland constants.
129
130 C enums and preprocessor macros with numerical or string expressions are
131 automatically discovered and registered as constants.
132
133 ### Implementations
134
135 Implementations are the userland visible interfaces to the foreign function interface.
136
137 ```php
138 function str\error(int $num) : string {
139 let errnum = intval($num);
140 return strerror(errnum) as to_string(strerror);
141 }
142 ```
143
144 Each implementation refers to exactly one declared foreign function referenced in its `return` statement. Each native function, on the other hand, may have any number of implementations.
145
146 ## Complete example
147
148 ```c
149 #ifdef __linux__
150 /* needed for setkey() in stdlib.h */
151 # pragma lib "crypt"
152 #endif
153
154 /* for free() */
155 #include <stdlib.h>
156
157 #pragma lib "idn"
158 #include <idna.h>
159
160 function idn\utf8_to_ascii(string $host, string &$result, int $flags = 0) : int {
161 // there must be a `let` statement for each
162 // declared argument of the called function
163
164 // setup a pointer to NULL
165 let buffer = &NULL;
166
167 // setup a string pointer to $host
168 let host = strval($host);
169
170 // assing the integer value of $flags
171 let flags = intval($flags);
172
173 // the function to call is referenced in
174 // the return statement, along with the
175 // necessary cast how to interpret the
176 // returned native value
177 return idna_to_ascii_8z(host, buffer, flags)
178 as to_int(idna_to_ascii_8z);
179
180 // by-ref vars might receive output values
181 // through `set` statments, which also
182 // require a cast how to marshal the
183 // native data as PHP value
184 set $result = to_string(*buffer);
185
186 // after the buffer has been marshaled
187 // for the PHP engine, we have to free
188 // the buffer to avoid a memory leak
189 free free(*buffer);
190 // note that in this example we omit the
191 // declaration of the free() function called
192 // in our `free` statement for brevity
193 }
194
195 function idn\strerror(int $rc) : string {
196 return to_string(idna_strerror);
197 let rc = intval($rc);
198 }
199 ```
200
201 ### Userland
202
203 ```php
204 $rc = idn\utf8_to_ascii("flöte.de", $result);
205 printf("<%s>\n", $result);
206 printf("%s\n", idn\strerror($rc));
207
208 $rc = idn\utf8_to_ascii("…asdf….de", $result, IDNA_USE_STD3_ASCII_RULES);
209 printf("<%s>\n", $result);
210 printf("%s\n", idn\strerror($rc));
211 ```
212
213 #### Output
214 ```
215 <xn--flte-6qa.de>
216 Success
217 <>
218 Non-digit/letter/hyphen in input
219 ```
220
221 ## License
222
223 ext-psi is licensed under the 2-Clause-BSD license, which can be found in
224 the accompanying [LICENSE](./LICENSE) file.
225
226 ## Contributing
227
228 All forms of contribution are welcome! Please see the bundled
229 [CONTRIBUTING](./CONTRIBUTING.md) note for the general principles followed.
230
231 The list of past and current contributors is maintained in [THANKS](./THANKS).