fix package.xml
[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 with php-src@master yet.
26
27 ### PECL
28
29 This extension is distributed through [PECL](http://pecl.php.net) and can be
30 installed with [PEAR](http://pear.php.net)'s pecl command:
31
32 pecl install psi
33
34 ### PHARext
35
36 Watch out for [PECL replicates](https://replicator.pharext.org?psi)
37 and [pharext](https://github.com/pharext) packages attached to
38 [releases](https://github.com/m6w6/ext-psi/releases).
39
40 ### Checkout
41
42 This extension is hosted at [Github](https://github.com/m6w6/ext-psi) with a
43 personal [mirror](https://git.m6w6.name/?p=m6w6/ext-psi) available.
44
45 git clone github.com:m6w6/ext-psi
46
47 cd ext-psi
48
49 /path/to/phpize
50 ./configure --with-php-config=/path/to/php-config
51 make
52 sudo make install
53
54 ## Configuring PSI at build time
55
56 PSI supports the following configure switches:
57
58 ### --enable-psi
59 **Enable PHP System Interface support.**
60
61 This is only relevant for an in-tree build. Use `--enable-psi` to include
62 the PSI extension in the build.
63
64 ### --with-psi-libjit
65 **Path to libjit.**
66
67 > **WARNING:**
68 > We currently rely on a patched libjit, because of an apparent bug in how
69 > libjit creates closures, which still needs to be verified, though.
70 > See https://github.com/m6w6/libjit for the preliminary patch.
71
72 ### --with-psi-libffi
73 **Path to libffi.**
74
75 ## Configuring PSI at runtime
76
77 ### psi.engine
78
79 The backend that PSI should use as FFI, either _jit_ for `libjit` or _ffi_ for `libffi`. Defaults to "ffi".
80
81 ### psi.directory
82
83 A colon separated list of directories to scan for `*.psi` files. Defaults to "psi.d".
84
85 ### psi.blacklist.decls
86
87 A comma separated list of C function declarations to ignore.
88
89 ### psi.blacklist.vars
90
91 A comma separated list of C variable declarations to ignore.
92
93 ## PSI files
94
95 ### CPP
96
97 * conditional parsing
98 * including headers
99
100 ```c
101 #include <string.h>
102 ```
103
104 ### Comments
105
106 * C style multi line comments
107 * C++ style single line comments
108
109 ```c
110 // this is a one line comment
111 /* followed
112 by a multi
113 line comment
114 */
115 ```
116
117 ### Typedefs
118
119 ```c
120 typedef unsigned char xmlChar;
121 ```
122
123 They follow the basic C-style `typedef` syntax.
124
125 ```c
126 typedef struct str {
127 char *p;
128 size_t l;
129 } str_t;
130 ```
131 You can also `typedef` unions and enums that way.
132
133 ### Structs
134
135 The following example results in exactly the same interpretation as the previous:
136
137 ```c
138 typedef struct str str_t;
139 struct str {
140 char *p;
141 size_t l;
142 }
143 ```
144
145 A struct will have the size of all its elements plus padding combined and an
146 alignment equal to that of the largest element's alignment.
147
148 ### Enums
149
150 Enums are considered to be of type `int`.
151
152 ```c
153 enum STATUS {
154 FAILURE = -1,
155 SUCCESS
156 }
157 ```
158
159 Enums will be registered as userland constants with the following pattern:
160
161 * `psi\STATUS\FAILURE` with value -1
162 * `psi\STATUS\SUCCESS` with value 0
163
164 ### Unions
165
166 ```c
167 union anyval {
168 char c;
169 short s;
170 int i;
171 long l;
172 float f;
173 double d;
174 str_t str;
175 }
176 ```
177
178 Unions will have the size and alignment of the largest element they contain.
179
180 ### Lib
181
182 ```c
183 lib "awesome";
184 ```
185
186 These statements define what library should be `dlopen()`-ed to look up symbols from declarations.
187 When a `lib` statement is omitted, stdlib is assumed.
188
189 ### Declarations
190
191 Declarations provide all information needed to make a foreign function call.
192
193 ```c
194 extern char *strerror(int errnum);
195 ```
196
197 You may specify a non-standard calling convention in place of `extern`, where `default` and `cdecl` have the same meaning as `extern`.
198
199 Additionally recognized calling conventions include: `stdcall` and `fastcall`.
200
201 ### Constants
202
203 ```c
204 const int num\ZERO = 0;
205 const string pwd\TOKEN = "4WlOjXGL";
206 ```
207
208 Constants must have a namespaced identifiers and are registered as userland constants.
209
210 ### Implementations
211
212 Implementations are the userland visible interfaces to the foreign function interface.
213
214 ```php
215 function str\error(int $num) : string {
216 let errnum = intval($num);
217 return to_string(strerror);
218 }
219 ```
220
221 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.
222
223 ## Complete example
224
225 ```c
226 // all declarations in this file should be looked up in libidn
227 lib "idn";
228
229 // IDNA errors
230 const int \IDNA_SUCCESS = 0;
231 const int \IDNA_STRINGPREP_ERROR = 1;
232 const int \IDNA_PUNYCODE_ERROR = 2;
233 const int \IDNA_CONTAINS_NON_LDH = 3;
234 const int \IDNA_CONTAINS_LDH = 3;
235 const int \IDNA_CONTAINS_MINUS = 4;
236 const int \IDNA_INVALID_LENGTH = 5;
237 const int \IDNA_NO_ACE_PREFIX = 6;
238 const int \IDNA_ROUNDTRIP_VERIFY_ERROR = 7;
239 const int \IDNA_CONTAINS_ACE_PREFIX = 8;
240 const int \IDNA_ICONV_ERROR = 9;
241 const int \IDNA_MALLOC_ERROR = 201;
242 const int \IDNA_DLOPEN_ERROR = 202;
243 // IDNA flags
244 const int \IDNA_ALLOW_UNASSIGNED = 1;
245 const int \IDNA_USE_STD3_ASCII_RULES = 2;
246
247 // nothing special about the declaration here
248 default int idna_to_ascii_8z(char *host, char **buffer, int flags);
249
250 function idn\utf8_to_ascii(string $host, string &$result, int $flags = 0) : int {
251 // there must be a `let` statement for each
252 // declared argument of the called function
253
254 // setup a pointer to NULL
255 let buffer = &NULL;
256
257 // setup a string pointer to $host
258 let host = strval($host);
259
260 // assing the integer value of $flags
261 let flags = intval($flags);
262
263 // the function to call is referenced in
264 // the return statement, along with the
265 // neccessary cast how to interpred the
266 // returned native value
267 return to_int(idna_to_ascii_8z);
268
269 // by-ref vars might receive output values
270 // through `set` statments, which also
271 // require a cast how to marshal the
272 // native data as PHP value
273 set $result = to_string(*buffer);
274
275 // after the buffer has been marshaled
276 // for the PHP engine, we have to free
277 // the buffer to avoid a memory leak
278 free free(*buffer);
279 // note that in this example we omit the
280 // declaration of the free() function called
281 // in our `free` statement for brevity
282 }
283
284 default char *idna_strerror(int rc);
285 function idn\strerror(int $rc) : string {
286 return to_string(idna_strerror);
287 let rc = intval($rc);
288 }
289 ```
290
291 ### Userland
292
293 ```php
294 $rc = idn\utf8_to_ascii("flöte.de", $result);
295 printf("<%s>\n", $result);
296 printf("%s\n", idn\strerror($rc));
297
298 $rc = idn\utf8_to_ascii("…asdf….de", $result, IDNA_USE_STD3_ASCII_RULES);
299 printf("<%s>\n", $result);
300 printf("%s\n", idn\strerror($rc));
301 ```
302
303 #### Output
304 ```
305 <xn--flte-6qa.de>
306 Success
307 <>
308 Non-digit/letter/hyphen in input
309 ```
310
311 ## ChangeLog
312
313 A comprehensive list of changes can be obtained from the
314 [PECL website](https://pecl.php.net/package-changelog.php?package=psi).
315
316 Known issues are listed in [BUGS](./BUGS) and future ideas can be found in [TODO](./TODO).
317
318 ## License
319
320 ext-psi is licensed under the 2-Clause-BSD license, which can be found in
321 the accompanying [LICENSE](./LICENSE) file.
322
323 ## Contributing
324
325 All forms of contribution are welcome! Please see the bundled
326 [CONTRIBUTING](./CONTRIBUTING.md) note for the general principles followed.
327
328 The list of past and current contributors is maintained in [THANKS](./THANKS).