2 * Copyright (C) 2009-2010 Red Hat Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 (* Please read generator/README first. *)
26 open Generator_docstrings
27 open Generator_optgroups
28 open Generator_actions
29 open Generator_structs
32 let rec generate_php_h () =
33 generate_header CStyle LGPLv2plus;
36 #ifndef PHP_GUESTFS_PHP_H
37 #define PHP_GUESTFS_PHP_H 1
43 #define PHP_GUESTFS_PHP_EXTNAME \"guestfs_php\"
44 #define PHP_GUESTFS_PHP_VERSION \"1.0\"
46 PHP_MINIT_FUNCTION (guestfs_php);
48 #define PHP_GUESTFS_HANDLE_RES_NAME \"guestfs_h\"
50 PHP_FUNCTION (guestfs_create);
51 PHP_FUNCTION (guestfs_last_error);
55 fun (shortname, _, _, _, _, _, _) ->
56 pr "PHP_FUNCTION (guestfs_%s);\n" shortname
57 ) all_functions_sorted;
61 extern zend_module_entry guestfs_php_module_entry;
62 #define phpext_guestfs_php_ptr &guestfs_php_module_entry
64 #endif /* PHP_GUESTFS_PHP_H */
67 and generate_php_c () =
68 generate_header CStyle LGPLv2plus;
71 /* NOTE: Be very careful with all macros in PHP header files. The
72 * morons who wrote them aren't good at making them safe for inclusion
73 * in arbitrary places in C code, eg. not using 'do ... while(0)'
74 * or parenthesizing any of the arguments.
77 /* NOTE (2): Some parts of the API can't be used on 32 bit platforms.
78 * Any 64 bit numbers will be truncated. There's no easy way around
88 #include <php_guestfs_php.h>
90 #include \"guestfs.h\"
92 static int res_guestfs_h;
95 guestfs_php_handle_dtor (zend_rsrc_list_entry *rsrc TSRMLS_DC)
97 guestfs_h *g = (guestfs_h *) rsrc->ptr;
102 PHP_MINIT_FUNCTION (guestfs_php)
105 zend_register_list_destructors_ex (guestfs_php_handle_dtor,
106 NULL, PHP_GUESTFS_HANDLE_RES_NAME, module_number);
109 static function_entry guestfs_php_functions[] = {
110 PHP_FE (guestfs_create, NULL)
111 PHP_FE (guestfs_last_error, NULL)
115 fun (shortname, _, _, _, _, _, _) ->
116 pr " PHP_FE (guestfs_%s, NULL)\n" shortname
117 ) all_functions_sorted;
119 pr " { NULL, NULL, NULL }
122 zend_module_entry guestfs_php_module_entry = {
123 #if ZEND_MODULE_API_NO >= 20010901
124 STANDARD_MODULE_HEADER,
126 PHP_GUESTFS_PHP_EXTNAME,
127 guestfs_php_functions,
128 PHP_MINIT (guestfs_php),
133 #if ZEND_MODULE_API_NO >= 20010901
134 PHP_GUESTFS_PHP_VERSION,
136 STANDARD_MODULE_PROPERTIES
139 #ifdef COMPILE_DL_GUESTFS_PHP
140 ZEND_GET_MODULE (guestfs_php)
143 PHP_FUNCTION (guestfs_create)
145 guestfs_h *g = guestfs_create ();
150 guestfs_set_error_handler (g, NULL, NULL);
152 ZEND_REGISTER_RESOURCE (return_value, g, res_guestfs_h);
155 PHP_FUNCTION (guestfs_last_error)
160 if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, \"r\",
165 ZEND_FETCH_RESOURCE (g, guestfs_h *, &z_g, -1, PHP_GUESTFS_HANDLE_RES_NAME,
171 const char *err = guestfs_last_error (g);
173 RETURN_STRING (err, 1);
181 (* Now generate the PHP bindings for each action. *)
183 fun (shortname, (ret, args, optargs as style), _, _, _, _, _) ->
184 pr "PHP_FUNCTION (guestfs_%s)\n" shortname;
187 pr " guestfs_h *g;\n";
191 | String n | Device n | Pathname n | Dev_or_Path n
192 | FileIn n | FileOut n | Key n
196 pr " int %s_size;\n" n
199 pr " zval *z_%s;\n" n;
200 pr " char **%s;\n" n;
202 pr " zend_bool %s;\n" n
203 | Int n | Int64 n | Pointer (_, n) ->
207 if optargs <> [] then (
208 pr " struct guestfs_%s_argv optargs_s = { .bitmask = 0 };\n" shortname;
209 pr " struct guestfs_%s_argv *optargs = &optargs_s;\n" shortname;
211 (* XXX Ugh PHP doesn't have proper optional arguments, so we
212 * have to use sentinel values.
214 (* Since we don't know if PHP types will exactly match structure
215 * types, declare some local variables here.
219 | Bool n -> pr " zend_bool optargs_t_%s = -1;\n" n
220 | Int n | Int64 n -> pr " long optargs_t_%s = -1;\n" n
222 pr " char *optargs_t_%s = NULL;\n" n;
223 pr " int optargs_t_%s_size = -1;\n" n
230 (* Parse the parameters. *)
231 let param_string = String.concat "" (
234 | String n | Device n | Pathname n | Dev_or_Path n
235 | FileIn n | FileOut n | BufferIn n | Key n -> "s"
236 | OptString n -> "s!"
237 | StringList n | DeviceList n -> "a"
239 | Int n | Int64 n | Pointer (_, n) -> "l"
244 if optargs <> [] then
250 | Int _ | Int64 _ -> "l"
257 pr " if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, \"r%s\",\n"
262 | String n | Device n | Pathname n | Dev_or_Path n
263 | FileIn n | FileOut n | BufferIn n | Key n
265 pr ", &%s, &%s_size" n n
266 | StringList n | DeviceList n ->
270 | Int n | Int64 n | Pointer (_, n) ->
275 | Bool n | Int n | Int64 n ->
276 pr ", &optargs_t_%s" n
278 pr ", &optargs_t_%s, &optargs_t_%s_size" n n
281 pr ") == FAILURE) {\n";
282 pr " RETURN_FALSE;\n";
285 pr " ZEND_FETCH_RESOURCE (g, guestfs_h *, &z_g, -1, PHP_GUESTFS_HANDLE_RES_NAME,\n";
286 pr " res_guestfs_h);\n";
287 pr " if (g == NULL) {\n";
288 pr " RETURN_FALSE;\n";
294 | String n | Device n | Pathname n | Dev_or_Path n
295 | FileIn n | FileOut n | Key n
297 (* Just need to check the string doesn't contain any ASCII
298 * NUL characters, which won't be supported by the C API.
300 pr " if (strlen (%s) != %s_size) {\n" n n;
301 pr " fprintf (stderr, \"libguestfs: %s: parameter '%s' contains embedded ASCII NUL.\\n\");\n" shortname n;
302 pr " RETURN_FALSE;\n";
308 (* Convert array to list of strings.
309 * http://marc.info/?l=pecl-dev&m=112205192100631&w=2
312 pr " HashTable *a;\n";
314 pr " HashPosition p;\n";
316 pr " size_t c = 0;\n";
318 pr " a = Z_ARRVAL_P (z_%s);\n" n;
319 pr " n = zend_hash_num_elements (a);\n";
320 pr " %s = safe_emalloc (n + 1, sizeof (char *), 0);\n" n;
321 pr " for (zend_hash_internal_pointer_reset_ex (a, &p);\n";
322 pr " zend_hash_get_current_data_ex (a, (void **) &d, &p) == SUCCESS;\n";
323 pr " zend_hash_move_forward_ex (a, &p)) {\n";
324 pr " zval t = **d;\n";
325 pr " zval_copy_ctor (&t);\n";
326 pr " convert_to_string (&t);\n";
327 pr " %s[c] = Z_STRVAL (t);\n" n;
330 pr " %s[c] = NULL;\n" n;
333 | Bool _ | Int _ | Int64 _ | Pointer _ -> ()
336 (* Optional arguments. *)
337 if optargs <> [] then (
338 let uc_shortname = String.uppercase shortname in
341 let n = name_of_argt argt in
342 let uc_n = String.uppercase n in
343 pr " if (optargs_t_%s != " n;
345 | Bool _ -> pr "((zend_bool)-1)"
346 | Int _ | Int64 _ -> pr "-1"
347 | String _ -> pr "NULL"
351 pr " optargs_s.%s = optargs_t_%s;\n" n n;
352 pr " optargs_s.bitmask |= GUESTFS_%s_%s_BITMASK;\n"
361 | RErr -> pr " int r;\n"
363 | RInt _ -> pr " int r;\n"
364 | RInt64 _ -> pr " int64_t r;\n"
365 | RConstString _ -> pr " const char *r;\n"
366 | RConstOptString _ -> pr " const char *r;\n"
371 | RStruct (_, typ) ->
372 pr " struct guestfs_%s *r;\n" typ
373 | RStructList (_, typ) ->
374 pr " struct guestfs_%s_list *r;\n" typ
382 (* Call the function. *)
384 pr " r = guestfs_%s " shortname
386 pr " r = guestfs_%s_argv " shortname;
387 generate_c_call_args ~handle:"g" style;
391 (* Free up parameters. *)
394 | String n | Device n | Pathname n | Dev_or_Path n
395 | FileIn n | FileOut n | Key n
401 pr " size_t c = 0;\n";
403 pr " for (c = 0; %s[c] != NULL; ++c)\n" n;
404 pr " efree (%s[c]);\n" n;
405 pr " efree (%s);\n" n;
408 | Bool _ | Int _ | Int64 _ | Pointer _ -> ()
411 (* Check for errors. *)
412 (match errcode_of_ret ret with
413 | `CannotReturnError -> ()
414 | `ErrorIsMinusOne ->
415 pr " if (r == -1) {\n";
416 pr " RETURN_FALSE;\n";
419 pr " if (r == NULL) {\n";
420 pr " RETURN_FALSE;\n";
425 (* Convert the return value. *)
430 pr " RETURN_BOOL (r);\n"
432 pr " RETURN_LONG (r);\n"
434 pr " RETURN_LONG (r);\n"
436 pr " RETURN_STRING (r, 1);\n"
437 | RConstOptString _ ->
438 pr " if (r) { RETURN_STRING (r, 1); }\n";
439 pr " else { RETURN_NULL (); }\n"
441 pr " char *r_copy = estrdup (r);\n";
443 pr " RETURN_STRING (r_copy, 0);\n"
445 pr " char *r_copy = estrndup (r, size);\n";
447 pr " RETURN_STRING (r_copy, 0);\n"
449 pr " size_t c = 0;\n";
450 pr " array_init (return_value);\n";
451 pr " for (c = 0; r[c] != NULL; ++c) {\n";
452 pr " add_next_index_string (return_value, r[c], 1);\n";
453 pr " free (r[c]);\n";
457 pr " size_t c = 0;\n";
458 pr " array_init (return_value);\n";
459 pr " for (c = 0; r[c] != NULL; c += 2) {\n";
460 pr " add_assoc_string (return_value, r[c], r[c+1], 1);\n";
461 pr " free (r[c]);\n";
462 pr " free (r[c+1]);\n";
465 | RStruct (_, typ) ->
466 let cols = cols_of_struct typ in
467 generate_php_struct_code typ cols
468 | RStructList (_, typ) ->
469 let cols = cols_of_struct typ in
470 generate_php_struct_list_code typ cols
475 ) all_functions_sorted
477 and generate_php_struct_code typ cols =
478 pr " array_init (return_value);\n";
482 pr " add_assoc_string (return_value, \"%s\", r->%s, 1);\n" name name
484 pr " add_assoc_stringl (return_value, \"%s\", r->%s, r->%s_len, 1);\n"
487 pr " add_assoc_stringl (return_value, \"%s\", r->%s, 32, 1);\n"
489 | name, (FBytes|FUInt64|FInt64|FInt32|FUInt32) ->
490 pr " add_assoc_long (return_value, \"%s\", r->%s);\n"
493 pr " add_assoc_stringl (return_value, \"%s\", &r->%s, 1, 1);\n"
495 | name, FOptPercent ->
496 pr " add_assoc_double (return_value, \"%s\", r->%s);\n"
499 pr " guestfs_free_%s (r);\n" typ
501 and generate_php_struct_list_code typ cols =
502 pr " array_init (return_value);\n";
503 pr " size_t c = 0;\n";
504 pr " for (c = 0; c < r->len; ++c) {\n";
505 pr " zval *z_elem;\n";
506 pr " ALLOC_INIT_ZVAL (z_elem);\n";
507 pr " array_init (z_elem);\n";
511 pr " add_assoc_string (z_elem, \"%s\", r->val[c].%s, 1);\n"
514 pr " add_assoc_stringl (z_elem, \"%s\", r->val[c].%s, r->val[c].%s_len, 1);\n"
517 pr " add_assoc_stringl (z_elem, \"%s\", r->val[c].%s, 32, 1);\n"
519 | name, (FBytes|FUInt64|FInt64|FInt32|FUInt32) ->
520 pr " add_assoc_long (z_elem, \"%s\", r->val[c].%s);\n"
523 pr " add_assoc_stringl (z_elem, \"%s\", &r->val[c].%s, 1, 1);\n"
525 | name, FOptPercent ->
526 pr " add_assoc_double (z_elem, \"%s\", r->val[c].%s);\n"
529 pr " add_next_index_zval (return_value, z_elem);\n";
531 pr " guestfs_free_%s_list (r);\n" typ