~ubuntu-branches/ubuntu/oneiric/swig1.3/oneiric

« back to all changes in this revision

Viewing changes to Source/Modules/php4.cxx

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2007-12-06 10:27:08 UTC
  • mfrom: (1.2.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20071206102708-t37t62i45n595w0e
Tags: 1.3.33-2ubuntu1
* Merge with Debian; remaining changes:
  - Drop support for pike.
  - Use python2.5 instead of python2.4.
  - Clean Runtime/ as well.
  - Force a few environment variables.
* debian/Rules (clean): Remove Lib/ocaml/swigp4.ml.

Show diffs side-by-side

added added

removed removed

Lines of Context:
10
10
 
11
11
/* FIXME: PHP5 OO wrapping TODO list:
12
12
 *
13
 
 * Short term (ideally before 1.3.30 is released):
 
13
 * Short term:
14
14
 *
15
15
 * Sort out auto-renaming of method and class names which are reserved
16
16
 *   words (e.g. empty, clone, exception, etc.) vs -php4/-php5 in some
27
27
 *   This is an optimisation - we could handle this case using a PHP
28
28
 *   default value, but currently we treat it as we would for a default
29
29
 *   value which is a compound C++ expression (i.e. as if we had a
30
 
 *   a method with two overloaded forms instead of a single method with
 
30
 *   method with two overloaded forms instead of a single method with
31
31
 *   a default parameter value).
32
32
 *
33
 
 * Create __isset method for PHP 5.1 and later (we can probably just
34
 
 *   always generate as PHP 5.0 should just ignore it).
35
 
 *
36
33
 * Long term:
37
34
 *
38
35
 * Option to generate code to work with PHP4 instead ("public $_cPtr;" ->
48
45
 * (may need to add more WARN_PHP4_xxx codes...)
49
46
 */
50
47
 
51
 
char cvsroot_php4_cxx[] = "$Header: /cvsroot/swig/SWIG/Source/Modules/php4.cxx,v 1.68 2006/11/01 23:54:52 wsfulton Exp $";
 
48
char cvsroot_php4_cxx[] = "$Id: php4.cxx 10099 2007-11-10 21:10:17Z wsfulton $";
52
49
 
53
50
#include "swigmod.h"
54
51
 
147
144
  static void (*r_prevtracefunc) (SwigType *t, String *mangled, String *clientdata) = 0;
148
145
}
149
146
 
150
 
static const char *php_header =
151
 
    "/*"
152
 
    "\n  +----------------------------------------------------------------------+"
153
 
    "\n  | PHP version 4.0                                                      |"
154
 
    "\n  +----------------------------------------------------------------------+"
155
 
    "\n  | Copyright (c) 1997, 1998, 1999, 2000, 2001 The PHP Group             |"
156
 
    "\n  +----------------------------------------------------------------------+"
157
 
    "\n  | This source file is subject to version 2.02 of the PHP license,      |"
158
 
    "\n  | that is bundled with this package in the file LICENSE, and is        |"
159
 
    "\n  | available at through the world-wide-web at                           |"
160
 
    "\n  | http://www.php.net/license/2_02.txt.                                 |"
161
 
    "\n  | If you did not receive a copy of the PHP license and are unable to   |"
162
 
    "\n  | obtain it through the world-wide-web, please send a note to          |"
163
 
    "\n  | license@php.net so we can mail you a copy immediately.               |"
164
 
    "\n  +----------------------------------------------------------------------+"
165
 
    "\n  | Authors:                                                             |"
166
 
    "\n  |                                                                      |"
167
 
    "\n  +----------------------------------------------------------------------+" "\n */\n";
168
 
 
169
147
void SwigPHP_emit_resource_registrations() {
170
148
  Iterator ki;
171
149
 
341
319
    Printf(f_make, "CXX_SOURCES=%s\n", withcxx);
342
320
    Printf(f_make, "C_SOURCES=%s\n", withc);
343
321
    Printf(f_make, "OBJS=%s_wrap.o $(C_SOURCES:.c=.o) $(CXX_SOURCES:.cxx=.o)\n", module);
344
 
    Printf(f_make, "MODULE=%s.`php -r 'switch(PHP_SHLIB_SUFFIX){case\"PHP_SHLIB_SUFFIX\":case\"dylib\":echo\"so\";break;default:echo PHP_SHLIB_SUFFIX;}'`\n",
345
 
           module);
 
322
    Printf(f_make, "MODULE=%s.so\n", module);
346
323
    Printf(f_make, "CFLAGS=-fpic\n");
347
324
    Printf(f_make, "LDFLAGS=-shared\n");
348
325
    Printf(f_make, "PHP_INC=`php-config --includes`\n");
350
327
    Printf(f_make, "EXTRA_LIB=\n\n");
351
328
    Printf(f_make, "$(MODULE): $(OBJS)\n");
352
329
    if (CPlusPlus || (withcxx != NULL)) {
353
 
      Printf(f_make, "\t$(CXX) $(LDFLAGS) $(OBJS) -o $(PROG) $(EXTRA_LIB)\n\n");
 
330
      Printf(f_make, "\t$(CXX) $(LDFLAGS) $(OBJS) -o $@ $(EXTRA_LIB)\n\n");
354
331
    } else {
355
 
      Printf(f_make, "\t$(CC) $(LDFLAGS) $(OBJS) -o $(PROG) $(EXTRA_LIB)\n\n");
 
332
      Printf(f_make, "\t$(CC) $(LDFLAGS) $(OBJS) -o $@ $(EXTRA_LIB)\n\n");
356
333
    }
357
334
    Printf(f_make, "%%.o: %%.cpp\n");
358
335
    Printf(f_make, "\t$(CXX) $(EXTRA_INC) $(PHP_INC) $(CFLAGS) -c $<\n");
394
371
      SWIG_exit(EXIT_FAILURE);
395
372
    }
396
373
 
397
 
    Printf(f_extra, "# $Id: php4.cxx,v 1.68 2006/11/01 23:54:52 wsfulton Exp $\n\n" "LTLIBRARY_NAME          = %s.la\n", module);
 
374
    Printf(f_extra, "# $Id: php4.cxx 10099 2007-11-10 21:10:17Z wsfulton $\n\n" "LTLIBRARY_NAME          = %s.la\n", module);
398
375
 
399
376
    // C++ has more and different entries to C in Makefile.in
400
377
    if (!CPlusPlus) {
441
418
      SWIG_exit(EXIT_FAILURE);
442
419
    }
443
420
 
444
 
    Printf(f_extra, "dnl $Id: php4.cxx,v 1.68 2006/11/01 23:54:52 wsfulton Exp $\n");
 
421
    Printf(f_extra, "dnl $Id: php4.cxx 10099 2007-11-10 21:10:17Z wsfulton $\n");
445
422
    Printf(f_extra, "dnl ***********************************************************************\n");
446
423
    Printf(f_extra, "dnl ** THIS config.m4 is provided for PHPIZE and PHP's consumption NOT\n");
447
424
    Printf(f_extra, "dnl ** for any part of the rest of the %s build system\n", module);
655
632
    Printf(s_oinit, "ZEND_INIT_MODULE_GLOBALS(%s, %s_init_globals, %s_destroy_globals);\n", module, module, module);
656
633
 
657
634
    /* start the header section */
658
 
    Printf(s_header, php_header);
659
635
    Printf(s_header, "ZEND_BEGIN_MODULE_GLOBALS(%s)\n", module);
660
 
    Printf(s_header, "char *error_msg;\n");
 
636
    Printf(s_header, "const char *error_msg;\n");
661
637
    Printf(s_header, "int error_code;\n");
662
638
    Printf(s_header, "ZEND_END_MODULE_GLOBALS(%s)\n", module);
663
639
    Printf(s_header, "ZEND_DECLARE_MODULE_GLOBALS(%s)\n", module);
709
685
    }
710
686
 
711
687
    Swig_banner(f_h);
712
 
    Printf(f_h, php_header);
713
688
 
714
689
    Printf(f_h, "\n\n");
715
690
    Printf(f_h, "#ifndef PHP_%s_H\n", cap_module);
738
713
    cs_entry = NULL;
739
714
 
740
715
    Printf(s_entry, "/* Every non-class user visible function must have an entry here */\n");
741
 
    Printf(s_entry, "static function_entry %s_functions[] = {\n", module);
 
716
    Printf(s_entry, "static zend_function_entry %s_functions[] = {\n", module);
742
717
 
743
718
    /* start the init section */
744
719
    Printv(s_init, "zend_module_entry ", module, "_module_entry = {\n" "#if ZEND_MODULE_API_NO > 20010900\n" "    STANDARD_MODULE_HEADER,\n" "#endif\n", NIL);
745
 
    Printf(s_init, "    \"%s\",\n", module);
 
720
    Printf(s_init, "    (char*)\"%s\",\n", module);
746
721
    Printf(s_init, "    %s_functions,\n", module);
747
722
    Printf(s_init, "    PHP_MINIT(%s),\n", module);
748
723
    Printf(s_init, "    PHP_MSHUTDOWN(%s),\n", module);
811
786
    Printf(s_init, "    return SUCCESS;\n");
812
787
    Printf(s_init, "}\n\n");
813
788
 
814
 
    Printf(s_init, "PHP_MSHUTDOWN_FUNCTION(%s)\n{\n", module);
815
 
    Printf(s_init, "%s\n", s_shutdown);
816
 
    Printf(s_init, "    return SUCCESS;\n");
817
 
    Printf(s_init, "}\n\n");
 
789
    Printv(s_init, "PHP_MSHUTDOWN_FUNCTION(", module, ")\n"
 
790
                   "{\n",
 
791
                   s_shutdown,
 
792
                   "#ifdef ZTS\n"
 
793
                   "    ts_free_id(", module, "_globals_id);\n"
 
794
                   "#endif\n"
 
795
                   "    return SUCCESS;\n"
 
796
                   "}\n\n", NIL);
818
797
 
819
798
    Printf(s_init, "PHP_RSHUTDOWN_FUNCTION(%s)\n{\n", module);
820
799
    Printf(s_init, "%s\n", r_shutdown);
876
855
 
877
856
  /* Just need to append function names to function table to register with PHP. */
878
857
  void create_command(String *cname, String *iname) {
879
 
    // This is for the single main function_entry record
 
858
    // This is for the single main zend_function_entry record
880
859
    if (shadow && php_version == 4) {
881
860
      if (wrapperType != standard)
882
861
        return;
883
862
    }
884
863
    Printf(f_h, "ZEND_NAMED_FUNCTION(%s);\n", iname);
885
 
    if (cs_entry) {
886
 
      Printf(cs_entry, " ZEND_NAMED_FE(%(lower)s,%s,NULL)\n", cname, iname);
887
 
    } else {
888
 
      Printf(s_entry, " ZEND_NAMED_FE(%(lower)s,%s,NULL)\n", cname, iname);
889
 
    }
 
864
    String * s = cs_entry;
 
865
    if (!s) s = s_entry;
 
866
    Printf(s, " SWIG_ZEND_NAMED_FE(%(lower)s,%s,NULL)\n", cname, iname);
890
867
  }
891
868
 
892
869
  /* ------------------------------------------------------------
968
945
    int newobject = GetFlag(n, "feature:new");
969
946
 
970
947
    Parm *p;
971
 
    int i, numopt;
 
948
    int i;
 
949
    int numopt;
972
950
    String *tm;
973
951
    Wrapper *f;
974
952
    bool mvr = (shadow && php_version == 4 && wrapperType == membervar);
1142
1120
        Replaceall(tm, "$input", source);
1143
1121
        Setattr(p, "emit:input", source);
1144
1122
        Printf(f->code, "%s\n", tm);
1145
 
        if (i == 0 && HashGetAttr(p, k_self)) {
 
1123
        if (i == 0 && Getattr(p, "self")) {
1146
1124
          Printf(f->code, "\tif(!arg1) SWIG_PHP_Error(E_ERROR, \"this pointer is NULL\");\n");
1147
1125
        }
1148
1126
        p = Getattr(p, "tmap:in:next");
1207
1185
      Replaceall(tm, "$result", "return_value");
1208
1186
      Replaceall(tm, "$owner", newobject ? "1" : "0");
1209
1187
      Printf(f->code, "%s\n", tm);
1210
 
      // are we returning a wrapable object?
1211
 
      // I don't know if this test is complete, I nicked it
1212
 
      if (is_shadow(d) && (SwigType_type(d) != T_ARRAY)) {
1213
 
        Printf(f->code, "/* Wrap this return value */\n");
 
1188
      // Are we returning a wrapable object?
 
1189
      if (shadow && php_version == 4 && is_shadow(d) && (SwigType_type(d) != T_ARRAY)) {
 
1190
        // Make object.
 
1191
        Printf(f->code, "{\n/* Wrap this return value */\n");
 
1192
        Printf(f->code, "zval *_cPtr;\n");
 
1193
        Printf(f->code, "ALLOC_ZVAL(_cPtr);\n");
 
1194
        Printf(f->code, "*_cPtr = *return_value;\n");
 
1195
        Printf(f->code, "INIT_ZVAL(*return_value);\n");
1214
1196
        if (native_constructor == NATIVE_CONSTRUCTOR) {
1215
 
          Printf(f->code, "if (this_ptr) {\n");
1216
 
          Printf(f->code, "/* NATIVE Constructor, use this_ptr */\n");
1217
 
          Printf(f->code, "zval *_cPtr; MAKE_STD_ZVAL(_cPtr);\n");
1218
 
          Printf(f->code, "*_cPtr = *return_value;\n");
1219
 
          Printf(f->code, "INIT_ZVAL(*return_value);\n");
1220
1197
          Printf(f->code, "add_property_zval(this_ptr,\"" SWIG_PTR "\",_cPtr);\n");
1221
 
          Printf(f->code, "} else if (! this_ptr) ");
1222
 
        }
1223
 
        {                       // THIS CODE only really needs writing out if the object to be returned
1224
 
          // Is being shadow-wrap-thingied
1225
 
          Printf(f->code, "{\n/* ALTERNATIVE Constructor, make an object wrapper */\n");
1226
 
          // Make object
1227
 
          String *shadowrettype = NewStringEmpty();
1228
 
          SwigToPhpType(d, iname, shadowrettype, (shadow && php_version == 4));
1229
 
 
1230
 
          Printf(f->code, "zval *obj, *_cPtr;\n");
1231
 
          Printf(f->code, "MAKE_STD_ZVAL(obj);\n");
1232
 
          Printf(f->code, "MAKE_STD_ZVAL(_cPtr);\n");
1233
 
          Printf(f->code, "*_cPtr = *return_value;\n");
1234
 
          Printf(f->code, "INIT_ZVAL(*return_value);\n");
1235
 
 
1236
 
          if (shadow && php_version == 4) {
1237
 
            Printf(f->code, "object_init_ex(obj,ptr_ce_swig_%s);\n", shadowrettype);
1238
 
            Printf(f->code, "add_property_zval(obj,\"" SWIG_PTR "\",_cPtr);\n");
1239
 
            Printf(f->code, "*return_value=*obj;\n");
1240
 
          } else {
1241
 
            Printf(f->code, "*return_value=*_cPtr;\n");
1242
 
          }
1243
 
          Printf(f->code, "}\n");
1244
 
        }
1245
 
      }                         // end of if-shadow lark
 
1198
        } else {
 
1199
          String *shadowrettype = SwigToPhpType(d, iname, true);
 
1200
          Printf(f->code, "object_init_ex(return_value,ptr_ce_swig_%s);\n", shadowrettype);
 
1201
          Delete(shadowrettype);
 
1202
          Printf(f->code, "add_property_zval(return_value,\"" SWIG_PTR "\",_cPtr);\n");
 
1203
        }
 
1204
        Printf(f->code, "}\n");
 
1205
      }
1246
1206
    } else {
1247
1207
      Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name);
1248
1208
    }
1254
1214
    if (cleanup) {
1255
1215
      Printv(f->code, cleanup, NIL);
1256
1216
    }
1257
 
    // What's this bit for?
 
1217
 
 
1218
    /* Look to see if there is any newfree cleanup code */
 
1219
    if (GetFlag(n, "feature:new")) {
 
1220
      if ((tm = Swig_typemap_lookup_new("newfree", n, "result", 0))) {
 
1221
        Printf(f->code, "%s\n", tm);
 
1222
        Delete(tm);
 
1223
      }
 
1224
    }
 
1225
 
 
1226
    /* See if there is any return cleanup code */
1258
1227
    if ((tm = Swig_typemap_lookup_new("ret", n, "result", 0))) {
1259
1228
      Printf(f->code, "%s\n", tm);
 
1229
      Delete(tm);
1260
1230
    }
1261
1231
 
 
1232
 
1262
1233
    if (mvr) {
1263
1234
      if (!mvrset) {
1264
1235
        Printf(f->code, "return _return_value;\n");
1290
1261
    Delete(wname);
1291
1262
    wname = NULL;
1292
1263
 
1293
 
    if (!(shadow && php_version == 5))
 
1264
    if (!(shadow && php_version == 5)) {
 
1265
      DelWrapper(f);
1294
1266
      return SWIG_OK;
 
1267
    }
1295
1268
 
1296
1269
    // Handle getters and setters.
1297
1270
    if (wrapperType == membervar) {
1318
1291
      bool handle_as_overload = false;
1319
1292
      String **arg_names;
1320
1293
      String **arg_values;
1321
 
      bool *arg_case = NULL;
1322
1294
      // Method or static method or plain function.
1323
1295
      const char *methodname = 0;
1324
1296
      String *output = s_oowrappers;
1428
1400
              l = nextSibling(l);
1429
1401
          }
1430
1402
        }
1431
 
 
1432
 
        arg_case = (bool *) malloc(max_num_of_arguments * sizeof(bool));
1433
 
        if (!arg_case) {
1434
 
          /* FIXME: How should this be handled?  The rest of SWIG just seems
1435
 
           * to not bother checking for malloc failing! */
1436
 
          fprintf(stderr, "Malloc failed!\n");
1437
 
          exit(1);
1438
 
        }
1439
 
        for (int i = 0; i < max_num_of_arguments; ++i) {
1440
 
          arg_case[i] = false;
1441
 
        }
1442
 
 
1443
 
        o = Getattr(n, "sym:overloaded");
1444
 
        while (o) {
1445
 
          ParmList *l2 = Getattr(o, "wrap:parms");
1446
 
          int num_arguments = emit_num_arguments(l2);
1447
 
          int num_required = emit_num_required(l2);
1448
 
          if (wrapperType == memberfn) {
1449
 
            --num_arguments;
1450
 
            --num_required;
1451
 
          }
1452
 
          for (int i = num_required; i <= num_arguments; ++i) {
1453
 
            arg_case[i] = true;
1454
 
          }
1455
 
          o = Getattr(o, "sym:nextSibling");
1456
 
        }
1457
1403
      }
1458
1404
 
1459
1405
      if (wrapperType == memberfn) {
1469
1415
        fprintf(stderr, "Malloc failed!\n");
1470
1416
        exit(1);
1471
1417
      }
1472
 
      for (int i = 0; i < max_num_of_arguments; ++i) {
 
1418
      for (i = 0; i < max_num_of_arguments; ++i) {
1473
1419
        arg_names[i] = NULL;
1474
1420
      }
1475
1421
 
1480
1426
        fprintf(stderr, "Malloc failed!\n");
1481
1427
        exit(1);
1482
1428
      }
1483
 
      for (int i = 0; i < max_num_of_arguments; ++i) {
 
1429
      for (i = 0; i < max_num_of_arguments; ++i) {
1484
1430
        arg_values[i] = NULL;
1485
1431
      }
1486
1432
 
1525
1471
              Printf(pname, " or_%s", pname_cstr);
1526
1472
            }
1527
1473
          }
1528
 
          const char *value = GetChar(p, "value");
1529
 
          if (value) {
 
1474
          String *value = NewString(Getattr(p, "value"));
 
1475
          if (Len(value)) {
1530
1476
            /* Check that value is a valid constant in PHP (and adjust it if
1531
1477
             * necessary, or replace it with "?" if it's just not valid). */
1532
1478
            SwigType *type = Getattr(p, "type");
1533
1479
            switch (SwigType_type(type)) {
1534
 
            case T_BOOL:{
1535
 
                if (strcmp(value, "true") == 0 || strcmp(value, "false") == 0)
 
1480
              case T_BOOL: {
 
1481
                if (Strcmp(value, "true") == 0 || Strcmp(value, "false") == 0)
1536
1482
                  break;
1537
1483
                char *p;
1538
1484
                errno = 0;
1539
1485
                int n = strtol(Char(value), &p, 0);
1540
 
                if (errno || *p)
1541
 
                  value = "?";
1542
 
                else if (n)
1543
 
                  value = "true";
1544
 
                else
1545
 
                  value = "false";
 
1486
                Clear(value);
 
1487
                if (errno || *p) {
 
1488
                  Append(value, "?");
 
1489
                } else if (n) {
 
1490
                  Append(value, "true");
 
1491
                } else {
 
1492
                  Append(value, "false");
 
1493
                }
1546
1494
                break;
1547
1495
              }
1548
 
            case T_CHAR:
1549
 
            case T_SCHAR:
1550
 
            case T_SHORT:
1551
 
            case T_INT:
1552
 
            case T_LONG:{
 
1496
              case T_CHAR:
 
1497
              case T_SCHAR:
 
1498
              case T_SHORT:
 
1499
              case T_INT:
 
1500
              case T_LONG: {
1553
1501
                char *p;
1554
1502
                errno = 0;
1555
1503
                (void) strtol(Char(value), &p, 0);
1556
 
                if (errno || *p)
1557
 
                  value = "?";
 
1504
                if (errno || *p) {
 
1505
                  Clear(value);
 
1506
                  Append(value, "?");
 
1507
                }
1558
1508
                break;
1559
1509
              }
1560
 
            case T_UCHAR:
1561
 
            case T_USHORT:
1562
 
            case T_UINT:
1563
 
            case T_ULONG:{
 
1510
              case T_UCHAR:
 
1511
              case T_USHORT:
 
1512
              case T_UINT:
 
1513
              case T_ULONG: {
1564
1514
                char *p;
1565
1515
                errno = 0;
1566
1516
                (void) strtoul(Char(value), &p, 0);
1567
 
                if (errno || *p)
1568
 
                  value = "?";
 
1517
                if (errno || *p) {
 
1518
                  Clear(value);
 
1519
                  Append(value, "?");
 
1520
                }
1569
1521
                break;
1570
1522
              }
1571
 
            case T_FLOAT:
1572
 
            case T_DOUBLE:{
 
1523
              case T_FLOAT:
 
1524
              case T_DOUBLE:{
1573
1525
                char *p;
1574
1526
                errno = 0;
1575
1527
                /* FIXME: strtod is locale dependent... */
1576
 
                (void) strtod(Char(value), &p);
1577
 
                if (errno || *p)
1578
 
                  value = "?";
 
1528
                double val = strtod(Char(value), &p);
 
1529
                if (errno || *p) {
 
1530
                  Clear(value);
 
1531
                  Append(value, "?");
 
1532
                } else if (strchr(Char(value), '.') == NULL) {
 
1533
                  // Ensure value is a double constant, not an integer one.
 
1534
                  Append(value, ".0");
 
1535
                  double val2 = strtod(Char(value), &p);
 
1536
                  if (errno || *p || val != val2) {
 
1537
                    Clear(value);
 
1538
                    Append(value, "?");
 
1539
                  }
 
1540
                }
1579
1541
                break;
1580
1542
              }
1581
 
            case T_REFERENCE:
1582
 
            case T_USER:
1583
 
            case T_ARRAY:
1584
 
              value = "?";
1585
 
              break;
1586
 
            case T_STRING:
1587
 
              if (Len(value) < 2) {
1588
 
                // How can a string (including "" be less than 2 characters?)
1589
 
                value = "?";
1590
 
              } else {
 
1543
              case T_REFERENCE:
 
1544
              case T_USER:
 
1545
              case T_ARRAY:
 
1546
                Clear(value);
 
1547
                Append(value, "?");
 
1548
                break;
 
1549
              case T_STRING:
 
1550
                if (Len(value) < 2) {
 
1551
                  // How can a string (including "" be less than 2 characters?)
 
1552
                  Clear(value);
 
1553
                  Append(value, "?");
 
1554
                } else {
 
1555
                  const char *v = Char(value);
 
1556
                  if (v[0] != '"' || v[Len(value) - 1] != '"') {
 
1557
                    Clear(value);
 
1558
                    Append(value, "?");
 
1559
                  }
 
1560
                  // Strings containing "$" require special handling, but we do
 
1561
                  // that later.
 
1562
                }
 
1563
                break;
 
1564
              case T_VOID:
 
1565
                assert(false);
 
1566
                break;
 
1567
              case T_POINTER: {
1591
1568
                const char *v = Char(value);
1592
 
                if (v[0] != '"' || v[Len(value) - 1] != '"')
1593
 
                  value = "?";
1594
 
                // Strings containing "$" require special handling, but we do that later.
1595
 
              }
1596
 
              break;
1597
 
            case T_VOID:
1598
 
              assert(false);
1599
 
              break;
1600
 
            case T_POINTER:{
1601
 
                const char *v = value;
1602
1569
                if (v[0] == '(') {
1603
1570
                  // Handle "(void*)0", "(TYPE*)0", "(char*)NULL", etc.
1604
1571
                  v += strcspn(v + 1, "*()") + 1;
1609
1576
                    } while (*v == '*');
1610
1577
                    if (*v++ == ')') {
1611
1578
                      v += strspn(v, " \t");
1612
 
                      value = v;
 
1579
                      String * old = value;
 
1580
                      value = NewString(v);
 
1581
                      Delete(old);
1613
1582
                    }
1614
1583
                  }
1615
1584
                }
1616
 
                if (strcmp(value, "NULL") == 0 || strcmp(value, "0") == 0 || strcmp(value, "0L") == 0) {
1617
 
                  value = "null";
 
1585
                if (Strcmp(value, "NULL") == 0 ||
 
1586
                    Strcmp(value, "0") == 0 ||
 
1587
                    Strcmp(value, "0L") == 0) {
 
1588
                  Clear(value);
 
1589
                  Append(value, "null");
1618
1590
                } else {
1619
 
                  value = "?";
 
1591
                  Clear(value);
 
1592
                  Append(value, "?");
1620
1593
                }
1621
1594
                break;
1622
1595
              }
1623
1596
            }
1624
1597
 
1625
1598
            if (!arg_values[argno]) {
1626
 
              arg_values[argno] = NewString(value);
 
1599
              arg_values[argno] = value;
 
1600
              value = NULL;
1627
1601
            } else if (Cmp(arg_values[argno], value) != 0) {
1628
1602
              // If a parameter has two different default values in
1629
1603
              // different overloaded forms of the function, we can't
1632
1606
              Delete(arg_values[argno]);
1633
1607
              arg_values[argno] = NewString("?");
1634
1608
            }
 
1609
          } else if (arg_values[argno]) {
 
1610
            // This argument already has a default value in another overloaded
 
1611
            // form, but doesn't in this form.  So don't try to do anything
 
1612
            // clever, just let the C wrappers resolve the overload and set the
 
1613
            // default values.
 
1614
            //
 
1615
            // This handling is safe, but I'm wondering if it may be overly
 
1616
            // conservative (FIXME) in some cases.  It seems it's only bad when
 
1617
            // there's an overloaded form with the appropriate number of
 
1618
            // parameters which doesn't want the default value, but I need to
 
1619
            // think about this more.
 
1620
            Delete(arg_values[argno]);
 
1621
            arg_values[argno] = NewString("?");
1635
1622
          }
 
1623
          Delete(value);
1636
1624
          p = nextSibling(p);
1637
1625
          ++argno;
1638
1626
        }
1725
1713
          if (i)
1726
1714
            Printf(args, ",");
1727
1715
          const char *value = Char(arg_values[i]);
1728
 
          bool non_php_default = (!value || strcmp(value, "?") == 0);
 
1716
          // FIXME: (really_overloaded && handle_as_overload) is perhaps a
 
1717
          // little conservative, but it doesn't hit any cases that it
 
1718
          // shouldn't for Xapian at least (and we need it to handle
 
1719
          // "Enquire::get_mset()" correctly).
 
1720
          bool non_php_default = ((really_overloaded && handle_as_overload) ||
 
1721
                                  !value || strcmp(value, "?") == 0);
1729
1722
          if (non_php_default)
1730
1723
            value = "null";
1731
1724
          Printf(args, "$%s=%s", arg_names[i], value);
1805
1798
            String *mangled = NewString("_p");
1806
1799
            Printf(mangled, "%s", SwigType_manglestr(ret_type));
1807
1800
            Node *class_node = Getattr(zend_types, mangled);
 
1801
            if (!class_node) {
 
1802
              /* This is needed when we're returning a pointer to a type
 
1803
               * rather than returning the type by value or reference. */
 
1804
              class_node = current_class;
 
1805
              Delete(mangled);
 
1806
              mangled = NewString(SwigType_manglestr(ret_type));
 
1807
              class_node = Getattr(zend_types, mangled);
 
1808
            }
1808
1809
            if (i.item) {
1809
1810
              Printf(output, "case \"%s\": ", mangled);
1810
1811
            } else {
1811
 
              Printf(output, "default: ", mangled);
 
1812
              Printf(output, "default: ");
1812
1813
            }
1813
1814
            const char *classname = GetChar(class_node, "sym:name");
1814
1815
            if (!classname)
1815
1816
              classname = GetChar(class_node, "name");
1816
 
            Printf(output, "return new %s%s($r);\n", prefix, classname);
 
1817
            if (classname)
 
1818
              Printf(output, "return new %s%s($r);\n", prefix, classname);
 
1819
            else
 
1820
              Printf(output, "return $r;\n");
1817
1821
            Delete(mangled);
1818
1822
          }
1819
1823
          Printf(output, "\t\t}\n");
1824
1828
      Printf(output, "\t}\n");
1825
1829
      Delete(prepare);
1826
1830
      Delete(invoke);
 
1831
      free(arg_values);
1827
1832
    }
1828
1833
 
 
1834
    DelWrapper(f);
 
1835
 
1829
1836
    return SWIG_OK;
1830
1837
  }
1831
1838
 
1858
1865
      Replaceall(tm, "$target", name);
1859
1866
      Printf(s_vinit, "%s\n", tm);
1860
1867
    } else {
1861
 
      Printf(stderr, "%s: Line %d, Unable to link with type %s\n", input_file, line_number, SwigType_str(t, 0), name);
 
1868
      Printf(stderr, "%s: Line %d, Unable to link with type %s\n", input_file, line_number, SwigType_str(t, 0));
1862
1869
    }
1863
1870
 
1864
1871
    /* Now generate PHP -> C sync blocks */
1868
1875
       Replaceall(tm, "$symname", iname);
1869
1876
       Printf(f_c->code, "%s\n", tm);
1870
1877
       } else {
1871
 
       Printf(stderr,"%s: Line %d, Unable to link with type %s\n", 
1872
 
       input_file, line_number, SwigType_str(t, 0), name);
 
1878
       Printf(stderr,"%s: Line %d, Unable to link with type %s\n",
 
1879
       input_file, line_number, SwigType_str(t, 0));
1873
1880
       }
1874
1881
     */
1875
1882
    /* Now generate C -> PHP sync blocks */
1881
1888
       Replaceall(tm, "$symname", iname);
1882
1889
       Printf(f_php->code, "%s\n", tm);
1883
1890
       } else {
1884
 
       Printf(stderr,"%s: Line %d, Unable to link with type %s\n", 
1885
 
       input_file, line_number, SwigType_str(t, 0), name);
 
1891
       Printf(stderr,"%s: Line %d, Unable to link with type %s\n",
 
1892
       input_file, line_number, SwigType_str(t, 0));
1886
1893
       }
1887
1894
       }
1888
1895
     */
1914
1921
    }
1915
1922
 
1916
1923
    if (shadow && php_version == 5) {
 
1924
      String *enumvalue = GetChar(n, "enumvalue");
 
1925
      String *set_to = iname;
 
1926
 
 
1927
      if (!enumvalue) {
 
1928
        enumvalue = GetChar(n, "enumvalueex");
 
1929
      }
 
1930
 
 
1931
      if (enumvalue) {
 
1932
        // Check for a simple constant expression which is valid in PHP.
 
1933
        // If we find one, initialise the const member with it; otherwise
 
1934
        // we initialise it using the C/C++ wrapped constant.
 
1935
        const char *p;
 
1936
        for (p = Char(enumvalue); *p; ++p) {
 
1937
          if (!isdigit((unsigned char)*p) && !strchr(" +-", *p)) {
 
1938
            // FIXME: enhance to handle `<previous_enum> + 1' which is what
 
1939
            // we get for enums that don't have an explicit value set.
 
1940
            break;
 
1941
          }
 
1942
        }
 
1943
        if (!*p) set_to = enumvalue;
 
1944
      }
 
1945
 
1917
1946
      if (wrapping_member_constant) {
1918
1947
        if (!s_oowrappers)
1919
1948
          s_oowrappers = NewStringEmpty();
1920
 
        Printf(s_oowrappers, "\n\tconst %s = %s;\n", wrapping_member_constant, iname);
 
1949
        Printf(s_oowrappers, "\n\tconst %s = %s;\n", wrapping_member_constant, set_to);
1921
1950
      } else {
1922
1951
        if (!s_fakeoowrappers)
1923
1952
          s_fakeoowrappers = NewStringEmpty();
1924
 
        Printf(s_fakeoowrappers, "\n\tconst %s = %s;\n", name, iname);
 
1953
        Printf(s_fakeoowrappers, "\n\tconst %s = %s;\n", name, set_to);
1925
1954
      }
1926
1955
    }
1927
1956
 
2258
2287
 
2259
2288
      if (base.item) {
2260
2289
        Printf(s_oinit,
2261
 
               "if (! (ptr_ce_swig_%s=zend_register_internal_class_ex(&ce_swig_%s,&ce_swig_%s,NULL))) zend_error(E_ERROR,\"Error registering wrapper for class %s\");\n",
 
2290
               "if (! (ptr_ce_swig_%s=zend_register_internal_class_ex(&ce_swig_%s,&ce_swig_%s,NULL TSRMLS_CC))) zend_error(E_ERROR,\"Error registering wrapper for class %s\");\n",
2262
2291
               shadow_classname, shadow_classname, GetChar(base.item, "sym:name"), shadow_classname);
2263
2292
      } else {
2264
2293
        Printf(s_oinit,
2265
 
               "if (! (ptr_ce_swig_%s=zend_register_internal_class_ex(&ce_swig_%s,NULL,NULL))) zend_error(E_ERROR,\"Error registering wrapper for class %s\");\n",
 
2294
               "if (! (ptr_ce_swig_%s=zend_register_internal_class_ex(&ce_swig_%s,NULL,NULL TSRMLS_CC))) zend_error(E_ERROR,\"Error registering wrapper for class %s\");\n",
2266
2295
               shadow_classname, shadow_classname, shadow_classname);
2267
2296
      }
2268
2297
      Printf(s_oinit, "\n");
2325
2354
          }
2326
2355
        } else {
2327
2356
          Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_set';\n", shadow_classname);
2328
 
          Printf(s_phpclasses, "\t\tif (function_exists($func) call_user_func($func,$this->%s,$value);\n", SWIG_PTR);
2329
 
        }
2330
 
        Printf(s_phpclasses, "\t}\n");
2331
 
        /* FIXME: also create __isset for PHP 5.1 and later? */
 
2357
          Printf(s_phpclasses, "\t\tif (function_exists($func)) call_user_func($func,$this->%s,$value);\n", SWIG_PTR);
 
2358
        }
 
2359
        Printf(s_phpclasses, "\t}\n");
 
2360
 
 
2361
        /* Create __isset for PHP 5.1 and later; PHP 5.0 will just ignore it. */
 
2362
        Printf(s_phpclasses, "\n\tfunction __isset($var) {\n");
 
2363
        // FIXME: tune this threshold, but it should probably be different to
 
2364
        // that for __set() and __get() as we don't need to call_user_func()
 
2365
        // here...
 
2366
        if (Len(shadow_set_vars) == 1) {
 
2367
          // Only one setter, so just check the name.
 
2368
          Printf(s_phpclasses, "\t\treturn ");
 
2369
          while (ki.key) {
 
2370
              key = ki.key;
 
2371
              Printf(s_phpclasses, "$var == '%s'", ki.key);
 
2372
              ki = Next(ki);
 
2373
              if (ki.key) Printf(s_phpclasses, " || ");
 
2374
          }
 
2375
          Printf(s_phpclasses, ";\n");
 
2376
        } else {
 
2377
          Printf(s_phpclasses, "\t\treturn function_exists('%s_'.$var.'_set');\n", shadow_classname);
 
2378
        }
 
2379
        Printf(s_phpclasses, "\t}\n");
2332
2380
      }
2333
2381
      // Write property GET handlers
2334
2382
      ki = First(shadow_get_vars);
2346
2394
          }
2347
2395
        } else {
2348
2396
          Printf(s_phpclasses, "\t\t$func = '%s_'.$var.'_get';\n", shadow_classname);
2349
 
          Printf(s_phpclasses, "\t\tif (function_exists($func) return call_user_func($func,$this->%s);\n", SWIG_PTR);
 
2397
          Printf(s_phpclasses, "\t\tif (function_exists($func)) return call_user_func($func,$this->%s);\n", SWIG_PTR);
2350
2398
        }
2351
2399
        // Reading an unknown property name gives null in PHP.
2352
2400
        Printf(s_phpclasses, "\t\treturn null;\n");
2482
2530
    Delete(class_iname);
2483
2531
    Delete(mget);
2484
2532
    Delete(mset);
 
2533
    DelWrapper(f);
2485
2534
 
2486
2535
    return SWIG_OK;
2487
2536
  }
2509
2558
  }
2510
2559
 
2511
2560
 
2512
 
  void SwigToPhpType(SwigType *t, String_or_char *pname, String *php_type, int shadow_flag) {
 
2561
  String * SwigToPhpType(SwigType *t, String_or_char *pname, int shadow_flag) {
2513
2562
    String *ptype = 0;
2514
2563
 
2515
2564
    if (shadow_flag) {
2519
2568
      ptype = PhpTypeFromTypemap((char *) "ptype", t, pname, (char *) "");
2520
2569
    }
2521
2570
 
2522
 
    if (ptype) {
2523
 
      Printf(php_type, "%s", ptype);
2524
 
      Delete(ptype);
2525
 
    } else {
2526
 
      /* Map type here */
2527
 
      switch (SwigType_type(t)) {
 
2571
    if (ptype) return ptype;
 
2572
 
 
2573
    /* Map type here */
 
2574
    switch (SwigType_type(t)) {
2528
2575
      case T_CHAR:
2529
2576
      case T_SCHAR:
2530
2577
      case T_UCHAR:
2539
2586
      case T_BOOL:
2540
2587
      case T_STRING:
2541
2588
      case T_VOID:
2542
 
        Printf(php_type, "");
2543
2589
        break;
2544
2590
      case T_POINTER:
2545
2591
      case T_REFERENCE:
2546
2592
      case T_USER:
2547
2593
        if (shadow_flag && is_shadow(t)) {
2548
 
          Printf(php_type, Char(is_shadow(t)));
2549
 
        } else {
2550
 
          Printf(php_type, "");
 
2594
          return NewString(Char(is_shadow(t)));
2551
2595
        }
2552
2596
        break;
2553
2597
      case T_ARRAY:
2556
2600
      default:
2557
2601
        Printf(stderr, "SwigToPhpType: unhandled data type: %s\n", SwigType_str(t, 0));
2558
2602
        break;
2559
 
      }
2560
2603
    }
 
2604
 
 
2605
    return NewStringEmpty();
2561
2606
  }
2562
2607
 
2563
 
 
2564
2608
  String *PhpTypeFromTypemap(char *op, SwigType *t, String_or_char *pname, String_or_char *lname) {
2565
2609
    String *tms;
2566
2610
    tms = Swig_typemap_lookup(op, t, pname, lname, (char *) "", (char *) "", NULL);
2605
2649
    char *iname = GetChar(n, "sym:name");
2606
2650
 
2607
2651
    if (shadow && php_version == 4) {
2608
 
      if (strcmp(iname, Char(shadow_classname)) == 0) {
 
2652
      if (iname && strcmp(iname, Char(shadow_classname)) == 0) {
2609
2653
        native_constructor = NATIVE_CONSTRUCTOR;
2610
2654
      } else {
2611
2655
        native_constructor = ALTERNATIVE_CONSTRUCTOR;