packages/lang/php5: Upgrade APC patch This patch upgrades the APC module patch to...
authorJo-Philipp Wich <jow@openwrt.org>
Fri, 22 Jan 2010 01:20:13 +0000 (01:20 +0000)
committerJo-Philipp Wich <jow@openwrt.org>
Fri, 22 Jan 2010 01:20:13 +0000 (01:20 +0000)
SVN-Revision: 19268

lang/php5/patches/002-uts_domainname.patch [deleted file]
lang/php5/patches/005-APC.patch

diff --git a/lang/php5/patches/002-uts_domainname.patch b/lang/php5/patches/002-uts_domainname.patch
deleted file mode 100644 (file)
index e69de29..0000000
index a7e7ee47253302b30a3baa35a7425237ad085cc2..d11859e2e16d25b1cfecb5313c9451b0a73d9068 100644 (file)
-diff -ubrN php-5.2.5-orig/ext/apc/apc.c php-5.2.5/ext/apc/apc.c
---- php-5.2.5-orig/ext/apc/apc.c       1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc.c    2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,554 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_bin.c php-5.3.1/ext/apc/apc_bin.c
+--- php-5.3.1.orig/ext/apc/apc_bin.c   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_bin.c        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,946 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2009 The PHP Group                                     |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
 +  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
++  | http://www.php.net/license/3_01.txt.                                 |
 +  | If you did not receive a copy of the PHP license and are unable to   |
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          George Schlossnagle <george@omniti.com>                     |
-+  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
-+  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
++  | Authors: Brian Shire <shire@php.net>                                 |
 +  +----------------------------------------------------------------------+
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++ */
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++/* $Id: apc_bin.c 284580 2009-07-22 06:05:31Z kalle $ */
 +
++/* Creates a binary architecture specific output to a string or file containing
++ * the current cache contents for both fies and user variables.  This is accomplished
++ * via the apc_copy_* functions and "swizzling" pointer values to a position
++ * independent value, and unswizzling them on restoration.
 + */
 +
-+/* $Id: apc.c,v 3.18 2007/11/29 22:15:53 shire Exp $ */
++#include "apc_globals.h"
++#include "apc_bin.h"
++#include "apc_zend.h"
++#include "apc_sma.h"
++#include "apc_pool.h"
++#include "ext/standard/md5.h"
++#include "ext/standard/crc32.h"
 +
-+#include "apc.h"
-+#include <regex.h>      /* for POSIX regular expressions */
-+#include "php.h"
++extern apc_cache_t* apc_cache;
++extern apc_cache_t* apc_user_cache;
 +
-+#define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
++extern int _apc_store(char *strkey, int strkey_len, const zval *val, const uint ttl, const int exclusive TSRMLS_DC); /* this is hacky */
 +
-+/* {{{ memory allocation wrappers */
++#define APC_BINDUMP_DEBUG 0
 +
-+void* apc_emalloc(size_t n)
-+{
-+    void* p = malloc(n);
-+    if (p == NULL) {
-+        apc_eprint("apc_emalloc: malloc failed to allocate %u bytes:", n);
-+    }
-+    return p;
-+}
 +
-+void* apc_erealloc(void* p, size_t n)
-+{
-+    p = realloc(p, n);
-+    if (p == NULL) {
-+        apc_eprint("apc_erealloc: realloc failed to allocate %u bytes:", n);
-+    }
-+    return p;
-+}
++#if APC_BINDUMP_DEBUG
 +
-+void apc_efree(void* p)
-+{
-+    if (p == NULL) {
-+        apc_eprint("apc_efree: attempt to free null pointer");
-+    }
-+    free(p);
-+}
++#define SWIZZLE(bd, ptr)  \
++    do { \
++        if((long)bd < (long)ptr && (ulong)ptr < ((long)bd + bd->size)) { \
++            printf("SWIZZLE: %x ~> ", ptr); \
++            ptr = (void*)((long)(ptr) - (long)(bd)); \
++            printf("%x in %s on line %d", ptr, __FILE__, __LINE__); \
++        } else if((long)ptr > bd->size) { /* not swizzled */ \
++            apc_eprint("pointer to be swizzled is not within allowed memory range! (%x < %x < %x) in %s on %d", (long)bd, ptr, ((long)bd + bd->size), __FILE__, __LINE__); \
++        } \
++        printf("\n"); \
++    } while(0);
 +
-+char* apc_estrdup(const char* s)
-+{
-+    int len;
-+    char* dup;
++#define UNSWIZZLE(bd, ptr)  \
++    do { \
++      printf("UNSWIZZLE: %x -> ", ptr); \
++      ptr = (void*)((long)(ptr) + (long)(bd)); \
++      printf("%x in %s on line %d \n", ptr, __FILE__, __LINE__); \
++    } while(0);
 +
-+    if (s == NULL) {
-+        return NULL;
-+    }
-+    len = strlen(s);
-+    dup = (char*) malloc(len+1);
-+    if (dup == NULL) {
-+        apc_eprint("apc_estrdup: malloc failed to allocate %u bytes:", len+1);
-+    }
-+    memcpy(dup, s, len);
-+    dup[len] = '\0';
-+    return dup;
-+}
++#else    /* !APC_BINDUMP_DEBUG */
 +
-+void* apc_xstrdup(const char* s, apc_malloc_t f)
-+{
-+    return s != NULL ? apc_xmemcpy(s, strlen(s)+1, f) : NULL;
-+}
++#define SWIZZLE(bd, ptr) \
++    do { \
++        if((long)bd < (long)ptr && (ulong)ptr < ((long)bd + bd->size)) { \
++            ptr = (void*)((long)(ptr) - (long)(bd)); \
++        } else if((ulong)ptr > bd->size) { /* not swizzled */ \
++            apc_eprint("pointer to be swizzled is not within allowed memory range! (%x < %x < %x) in %s on %d", (long)bd, ptr, ((long)bd + bd->size), __FILE__, __LINE__); \
++        } \
++    } while(0);
 +
-+void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f)
-+{
-+    void* q;
++#define UNSWIZZLE(bd, ptr) \
++    do { \
++      ptr = (void*)((long)(ptr) + (long)(bd)); \
++    } while(0);
 +
-+    if (p != NULL && (q = f(n)) != NULL) {
-+        memcpy(q, p, n);
-+        return q;
-+    }
-+    return NULL;
-+}
++#endif
 +
-+/* }}} */
 +
-+/* {{{ console display functions */
++static void *apc_bd_alloc(size_t size);
++static void apc_bd_free(void *ptr);
++static void *apc_bd_alloc_ex(void *ptr_new, size_t size);
 +
-+static void my_log(int level, const char* fmt, va_list args)
-+{
-+    static const char* level_strings[] = {
-+        "apc-debug",
-+        "apc-notice",
-+        "apc-warning",
-+        "apc-error"
-+    };
-+    static const int num_levels = NELEMS(level_strings);
++typedef void (*apc_swizzle_cb_t)(apc_bd_t *bd, zend_llist *ll, void *ptr TSRMLS_DC);
 +
-+    time_t now;
-+    char* buf;          /* for ctime */
++#if APC_BINDUMP_DEBUG
++#define apc_swizzle_ptr(bd, ll, ptr) _apc_swizzle_ptr(bd, ll, (void*)ptr, __FILE__, __LINE__ TSRMLS_CC)
++#else
++#define apc_swizzle_ptr(bd, ll, ptr) _apc_swizzle_ptr(bd, ll, (void*)ptr, NULL, 0 TSRMLS_CC)
++#endif
 +
-+    fflush(stdout);
++static void _apc_swizzle_ptr(apc_bd_t *bd, zend_llist *ll, void **ptr, const char* file, int line TSRMLS_DC);
++static void apc_swizzle_function(apc_bd_t *bd, zend_llist *ll, zend_function *func TSRMLS_DC);
++static void apc_swizzle_class_entry(apc_bd_t *bd, zend_llist *ll, zend_class_entry *ce TSRMLS_DC);
++static void apc_swizzle_hashtable(apc_bd_t *bd, zend_llist *ll, HashTable *ht, apc_swizzle_cb_t swizzle_cb, int is_ptr TSRMLS_DC);
++static void apc_swizzle_zval(apc_bd_t *bd, zend_llist *ll, zval *zv TSRMLS_DC);
++static void apc_swizzle_op_array(apc_bd_t *bd, zend_llist *ll, zend_op_array *op_array TSRMLS_DC);
++static void apc_swizzle_property_info(apc_bd_t *bd, zend_llist *ll, zend_property_info *pi TSRMLS_DC);
++static void apc_swizzle_function_entry(apc_bd_t *bd, zend_llist *ll, const zend_function_entry *fe TSRMLS_DC);
++static void apc_swizzle_arg_info_array(apc_bd_t *bd, zend_llist *ll, const zend_arg_info* arg_info_array, uint num_args TSRMLS_DC);
 +
-+    if (level < 0)
-+        level = 0;
-+    else if (level >= num_levels)
-+        level = num_levels-1;
-+    
-+    now = time(0);
-+    buf = ctime(&now);  /* TODO: replace with reentrant impl */
-+    buf[24] = '\0';
++static apc_bd_t* apc_swizzle_bd(apc_bd_t* bd, zend_llist *ll TSRMLS_DC);
++static int apc_unswizzle_bd(apc_bd_t *bd, int flags TSRMLS_DC);
 +
-+    fprintf(stderr, "[%s] [%s] ", buf, level_strings[level]);
-+    vfprintf(stderr, fmt, args);
 +
-+    if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') {
-+        fprintf(stderr, " %s", strerror(errno));
-+    }
-+    fprintf(stderr, "\n");
++/* {{{ apc_bd_alloc
++ *  callback for copy_* functions */
++static void *apc_bd_alloc(size_t size) {
++    return apc_bd_alloc_ex(NULL, size);
++} /* }}} */
 +
-+    if (level == APC_ERROR) {
-+        exit(2);
++
++/* {{{ apc_bd_free
++ *  callback for copy_* functions */
++static void apc_bd_free(void *ptr) {
++    size_t *size;
++    TSRMLS_FETCH();
++    if(zend_hash_index_find(&APCG(apc_bd_alloc_list), (ulong)ptr, (void**)&size) == FAILURE) {
++        apc_eprint("apc_bd_free could not free pointer (not found in list: %x)", ptr);
 +    }
-+}
++    APCG(apc_bd_alloc_ptr) = (void*)((size_t)APCG(apc_bd_alloc_ptr) - *size);
++    zend_hash_index_del(&APCG(apc_bd_alloc_list), (ulong)ptr);
++} /* }}} */
 +
-+void apc_log(int level, const char* fmt, ...)
-+{
-+    va_list args;
-+    va_start(args, fmt);
-+    my_log(level, fmt, args);
-+    va_end(args);
-+}
 +
-+void apc_eprint(const char* fmt, ...)
-+{
-+    va_list args;
-+    va_start(args, fmt);
-+    my_log(APC_ERROR, fmt, args);
-+    va_end(args);
-+}
++/* {{{ apc_bd_alloc_ex
++ *  set ranges or allocate a block of data from an already (e)malloc'd range.
++ *  if ptr_new is not NULL, it will reset the pointer to start at ptr_new,
++ *  with a range of size.  If ptr_new is NULL, returns the next available
++ *  block of given size.
++ */
++static void *apc_bd_alloc_ex(void *ptr_new, size_t size) {
++    void *rval;
++    TSRMLS_FETCH();
 +
-+void apc_wprint(const char* fmt, ...)
-+{
-+    va_list args;
-+    va_start(args, fmt);
-+    my_log(APC_WARNING, fmt, args);
-+    va_end(args);
-+}
++    rval = APCG(apc_bd_alloc_ptr);
++    if(ptr_new != NULL) {  /* reset ptrs */
++      APCG(apc_bd_alloc_ptr) = ptr_new;
++      APCG(apc_bd_alloc_ubptr) = (void*)((unsigned char *) ptr_new + size);
++    } else {  /* alloc block */
++      APCG(apc_bd_alloc_ptr) = (void*)((size_t)APCG(apc_bd_alloc_ptr) + size);
++#if APC_BINDUMP_DEBUG
++      apc_nprint("apc_bd_alloc: rval: 0x%x  ptr: 0x%x  ubptr: 0x%x  size: %d", rval, APCG(apc_bd_alloc_ptr), APCG(apc_bd_alloc_ubptr), size);
++#endif
++      if(APCG(apc_bd_alloc_ptr) > APCG(apc_bd_alloc_ubptr)) {
++          apc_eprint("Exceeded bounds check in apc_bd_alloc_ex by %d bytes.", (unsigned char *) APCG(apc_bd_alloc_ptr) - (unsigned char *) APCG(apc_bd_alloc_ubptr));
++      }
++      zend_hash_index_update(&APCG(apc_bd_alloc_list), (ulong)rval, &size, sizeof(size_t), NULL);
++    }
 +
-+void apc_nprint(const char* fmt, ...)
-+{
-+    va_list args;
-+    va_start(args, fmt);
-+    my_log(APC_NOTICE, fmt, args);
-+    va_end(args);
-+}
++    return rval;
++} /* }}} */
 +
-+void apc_dprint(const char* fmt, ...)
-+{
-+#ifdef APC_DEBUG
-+    va_list args;
-+    va_start(args, fmt);
-+    my_log(APC_DBG, fmt, args);
-+    va_end(args);
++
++/* {{{ _apc_swizzle_ptr */
++static void _apc_swizzle_ptr(apc_bd_t *bd, zend_llist *ll, void **ptr, const char* file, int line TSRMLS_DC) {
++    if(*ptr) {
++        if((long)bd < (long)*ptr && (ulong)*ptr < ((long)bd + bd->size)) {
++            zend_llist_add_element(ll, &ptr);
++#if APC_BINDUMP_DEBUG
++            printf("[%06d] apc_swizzle_ptr: %x -> %x ", zend_llist_count(ll), ptr, *ptr);
++            printf(" in %s on line %d \n", file, line);
 +#endif
-+}
++        } else if((ulong)ptr > bd->size) {
++            apc_eprint("pointer to be swizzled is not within allowed memory range! (%x < %x < %x) in %s on %d", (long)bd, *ptr, ((long)bd + bd->size), file, line); \
++        }
++    }
++} /* }}} */
 +
-+/* }}} */
 +
-+/* {{{ string and text manipulation */
++/* {{{ apc_swizzle_op_array */
++static void apc_swizzle_op_array(apc_bd_t *bd, zend_llist *ll, zend_op_array *op_array TSRMLS_DC) {
++    uint i;
 +
-+char* apc_append(const char* s, const char* t)
-+{
-+    int slen;
-+    int tlen;
-+    char* p;
++#ifdef ZEND_ENGINE_2
++    apc_swizzle_arg_info_array(bd, ll, op_array->arg_info, op_array->num_args TSRMLS_CC);
++    apc_swizzle_ptr(bd, ll, &op_array->arg_info);
++#else
++    if (op_array->arg_types) {
++        apc_swizzle_ptr(bd, ll, &op_array->arg_types);
++    }
++#endif
 +
-+    slen = strlen(s);
-+    tlen = strlen(t);
++    apc_swizzle_ptr(bd, ll, &op_array->function_name);
++    apc_swizzle_ptr(bd, ll, &op_array->filename);
++    apc_swizzle_ptr(bd, ll, &op_array->refcount);
 +
-+    p = (char*) apc_emalloc((slen + tlen + 1) * sizeof(char));
-+    memcpy(p, s, slen);
-+    memcpy(p + slen, t, tlen + 1);
++    /* swizzle op_array */
++    for(i=0; i < op_array->last; i++) {
++        if(op_array->opcodes[i].result.op_type == IS_CONST) {
++            apc_swizzle_zval(bd, ll, &op_array->opcodes[i].result.u.constant TSRMLS_CC);
++        }
++        if(op_array->opcodes[i].op1.op_type == IS_CONST) {
++            apc_swizzle_zval(bd, ll, &op_array->opcodes[i].op1.u.constant TSRMLS_CC);
++        }
++        if(op_array->opcodes[i].op2.op_type == IS_CONST) {
++            apc_swizzle_zval(bd, ll, &op_array->opcodes[i].op2.u.constant TSRMLS_CC);
++        }
++        switch (op_array->opcodes[i].opcode) {
++            case ZEND_JMP:
++                apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op1.u.jmp_addr);
++            case ZEND_JMPZ:
++            case ZEND_JMPNZ:
++            case ZEND_JMPZ_EX:
++            case ZEND_JMPNZ_EX:
++                apc_swizzle_ptr(bd, ll, &op_array->opcodes[i].op2.u.jmp_addr);
++        }
++    }
++    apc_swizzle_ptr(bd, ll, &op_array->opcodes);
 +
-+    return p;
-+}
++    /* break-continue array ptr */
++    if(op_array->brk_cont_array) {
++        apc_swizzle_ptr(bd, ll, &op_array->brk_cont_array);
++    }
 +
-+char* apc_substr(const char* s, int start, int length)
-+{
-+    char* substr;
-+    int src_len = strlen(s);
++    /* static voriables */
++    if(op_array->static_variables) {
++        apc_swizzle_hashtable(bd, ll, op_array->static_variables, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
++        apc_swizzle_ptr(bd, ll, &op_array->static_variables);
++    }
 +
-+    /* bring start into range */
-+    if (start < 0) {
-+        start = 0;
++#ifdef ZEND_ENGINE_2
++    /* try-catch */
++    if(op_array->try_catch_array) {
++        apc_swizzle_ptr(bd, ll, &op_array->try_catch_array);
 +    }
-+    else if (start >= src_len) {
-+        start = src_len - 1;
++#endif
++
++#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
++    /* vars */
++    if(op_array->vars) {
++        for(i=0; (signed int) i < op_array->last_var; i++) {
++            apc_swizzle_ptr(bd, ll, &op_array->vars[i].name);
++        }
++        apc_swizzle_ptr(bd, ll, &op_array->vars);
 +    }
++#endif
 +
-+    /* bring length into range */
-+    if (length < 0 || src_len - start < length) {
-+        length = src_len - start;
++#ifdef ZEND_ENGINE_2
++    /* doc comment */
++    if(op_array->doc_comment) {
++        apc_swizzle_ptr(bd, ll, &op_array->doc_comment);
 +    }
++#endif
 +
-+    /* create the substring */
-+    substr = apc_xmemcpy(s + start, length + 1, apc_emalloc);
-+    substr[length] = '\0';
-+    return substr;
-+}
++} /* }}} */
 +
-+char** apc_tokenize(const char* s, char delim)
-+{
-+    char** tokens;      /* array of tokens, NULL terminated */
-+    int size;           /* size of tokens array */
-+    int n;              /* index of next token in tokens array */
-+    int cur;            /* current position in input string */
-+    int end;            /* final legal position in input string */
-+    int next;           /* position of next delimiter in input */
-+    
-+    if (!s) {
-+        return NULL;
++
++/* {{{ apc_swizzle_function */
++static void apc_swizzle_function(apc_bd_t *bd, zend_llist *ll, zend_function *func TSRMLS_DC) {
++    apc_swizzle_op_array(bd, ll, &func->op_array TSRMLS_CC);
++#ifdef ZEND_ENGINE_2
++    if(func->common.scope) {
++        apc_swizzle_ptr(bd, ll, &func->common.scope);
 +    }
++#endif
++} /* }}} */
 +
-+    size = 2;
-+    n    = 0;
-+    cur  = 0;
-+    end  = strlen(s) - 1;
-+    
-+    tokens = (char**) apc_emalloc(size * sizeof(char*));
-+    tokens[n] = NULL;
 +
-+    while (cur <= end) {
-+        /* search for the next delimiter */
-+        char* p = strchr(s + cur, delim);
-+        next = p ? p-s : end+1;
++/* {{{ apc_swizzle_class_entry */
++static void apc_swizzle_class_entry(apc_bd_t *bd, zend_llist *ll, zend_class_entry *ce TSRMLS_DC) {
 +
-+        /* resize token array if necessary */
-+        if (n == size-1) {
-+            size *= 2;
-+            tokens = (char**) apc_erealloc(tokens, size * sizeof(char*));
-+        }
++    uint i;
 +
-+        /* save the current token */
-+        tokens[n] = apc_substr(s, cur, next-cur);
++    if(ce->name) {
++        apc_swizzle_ptr(bd, ll, &ce->name);
++    }
 +
-+        tokens[++n] = NULL;
-+        cur = next + 1;
++    if(ce->doc_comment) {
++        apc_swizzle_ptr(bd, ll, &ce->doc_comment);
 +    }
 +
-+    return tokens;
-+}
-+
-+/* }}} */
-+
-+/* {{{ filesystem functions */
++#ifndef ZEND_ENGINE_2
++    apc_swizzle_ptr(bd, ll, &ce->refcount);
++#endif
 +
-+#ifdef PHP_WIN32
-+int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC)
-+{
-+    char rpath[MAXPATHLEN];
-+    BY_HANDLE_FILE_INFORMATION fi;
-+    HANDLE f;
-+    
-+    if (VCWD_STAT(path, buf)) {
-+        return -1;
-+    }
++    apc_swizzle_hashtable(bd, ll, &ce->function_table, (apc_swizzle_cb_t)apc_swizzle_function, 0 TSRMLS_CC);
++    apc_swizzle_hashtable(bd, ll, &ce->default_properties, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
 +
-+    VCWD_REALPATH(path, rpath);
-+    f = CreateFile(rpath, 0, 0, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY, NULL);
-+    GetFileInformationByHandle(f, &fi);
-+    buf->st_ino = (ino_t)fi.nFileIndexLow;
-+    CloseHandle (f);
-+    return 0;
-+}
++#ifdef ZEND_ENGINE_2
++    apc_swizzle_hashtable(bd, ll, &ce->properties_info, (apc_swizzle_cb_t)apc_swizzle_property_info, 0 TSRMLS_CC);
 +#endif
 +
-+int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo)
-+{
-+    char** paths;
-+    char *exec_fname;
-+    int exec_fname_length;
-+    int found = 0;
-+    int i;
-+    TSRMLS_FETCH();
-+
-+    assert(filename && fileinfo);
++    apc_swizzle_hashtable(bd, ll, &ce->default_static_members, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
 +
-+    if (IS_ABSOLUTE_PATH(filename, strlen(filename)) && apc_stat(filename, &fileinfo->st_buf) == 0) {
-+        strncpy(fileinfo->fullpath, filename, MAXPATHLEN);
-+        return 0;
++    if(ce->static_members != &ce->default_static_members) {
++        apc_swizzle_hashtable(bd, ll, ce->static_members, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
++    } else {
++        apc_swizzle_ptr(bd, ll, &ce->static_members);
 +    }
 +
-+    paths = apc_tokenize(path, DEFAULT_DIR_SEPARATOR);
-+    if (!paths)
-+        return -1;
++    apc_swizzle_hashtable(bd, ll, &ce->constants_table, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
 +
-+    /* for each directory in paths, look for filename inside */
-+    for (i = 0; paths[i]; i++) {
-+        snprintf(fileinfo->fullpath, sizeof(fileinfo->fullpath), "%s%c%s", paths[i], DEFAULT_SLASH, filename);
-+        if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
-+            found = 1;
-+            break;
++    if(ce->builtin_functions) {
++        for(i=0; ce->builtin_functions[i].fname; i++) {
++            apc_swizzle_function_entry(bd, ll, &ce->builtin_functions[i] TSRMLS_CC);
 +        }
 +    }
 +
-+    /* check in path of the calling scripts' current working directory */
-+    /* modified from main/streams/plain_wrapper.c */
-+    if(!found && zend_is_executing(TSRMLS_C)) {
-+        exec_fname = zend_get_executed_filename(TSRMLS_C);
-+        exec_fname_length = strlen(exec_fname);
-+        while((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
-+        if((exec_fname && exec_fname[0] != '[') && exec_fname_length > 0) {
-+            /* not: [no active file] or no path */
-+            memcpy(fileinfo->fullpath, exec_fname, exec_fname_length);
-+            fileinfo->fullpath[exec_fname_length] = DEFAULT_SLASH;
-+            strcpy(fileinfo->fullpath +exec_fname_length +1, filename);
-+            /* apc_wprint("filename: %s, exec_fname: %s, fileinfo->fullpath: %s", filename, exec_fname, fileinfo->fullpath); */
-+            if (apc_stat(fileinfo->fullpath, &fileinfo->st_buf) == 0) {
-+                found = 1;
-+            }
-+        }
-+    }
-+    
-+    /* free the value returned by apc_tokenize */
-+    for (i = 0; paths[i]; i++) {
-+        apc_efree(paths[i]);
-+    }
-+    apc_efree(paths);
++    apc_swizzle_ptr(bd, ll, &ce->constructor);
++    apc_swizzle_ptr(bd, ll, &ce->destructor);
++    apc_swizzle_ptr(bd, ll, &ce->clone);
++    apc_swizzle_ptr(bd, ll, &ce->__get);
++    apc_swizzle_ptr(bd, ll, &ce->__set);
++    apc_swizzle_ptr(bd, ll, &ce->__unset);
++    apc_swizzle_ptr(bd, ll, &ce->__isset);
++    apc_swizzle_ptr(bd, ll, &ce->__call);
++    apc_swizzle_ptr(bd, ll, &ce->serialize_func);
++    apc_swizzle_ptr(bd, ll, &ce->unserialize_func);
 +
-+    return found ? 0 : -1;
-+}
++#ifdef ZEND_ENGINE_2_2
++    apc_swizzle_ptr(bd, ll, &ce->__tostring);
++#endif
 +
-+/* }}} */
++    apc_swizzle_ptr(bd, ll, &ce->filename);
++} /* }}} */
 +
-+/* {{{ regular expression wrapper functions */
 +
-+typedef struct {
-+    regex_t *reg;
-+    unsigned char type;
-+} apc_regex;
++/* {{{ apc_swizzle_property_info */
++static void apc_swizzle_property_info(apc_bd_t *bd, zend_llist *ll, zend_property_info *pi TSRMLS_DC) {
++    apc_swizzle_ptr(bd, ll, &pi->name);
++    apc_swizzle_ptr(bd, ll, &pi->doc_comment);
 +
-+void* apc_regex_compile_array(char* patterns[])
-+{
-+    apc_regex** regs;
-+    int npat;
-+    int i;
++#ifdef ZEND_ENGINE_2_2
++    apc_swizzle_ptr(bd, ll, &pi->ce);
++#endif
++} /* }}} */
 +
-+    if (!patterns)
-+        return NULL;
 +
-+    /* count the number of patterns in patterns */
-+    for (npat = 0; patterns[npat] != NULL; npat++) {}
++/* {{{ apc_swizzle_function_entry */
++static void apc_swizzle_function_entry(apc_bd_t *bd, zend_llist *ll, const zend_function_entry *fe TSRMLS_DC) {
++    apc_swizzle_ptr(bd, ll, &fe->fname);
++    apc_swizzle_arg_info_array(bd, ll, fe->arg_info, fe->num_args TSRMLS_CC);
++    apc_swizzle_ptr(bd, ll, &fe->arg_info);
++} /* }}} */
++
 +
-+    if (npat == 0)
-+        return NULL;
++/* {{{ apc_swizzle_arg_info_array */
++static void apc_swizzle_arg_info_array(apc_bd_t *bd, zend_llist *ll, const zend_arg_info* arg_info_array, uint num_args TSRMLS_DC) {
++    if(arg_info_array) {
++        uint i;
 +
-+    /* allocate the array of compiled expressions */
-+    regs = (apc_regex**) apc_emalloc(sizeof(apc_regex*) * (npat + 1));
-+    for (i = 0; i <= npat; i++) {
-+        regs[i] = (apc_regex *) apc_emalloc(sizeof(apc_regex));
-+        regs[i]->reg = NULL;
-+        regs[i]->type = APC_NEGATIVE_MATCH;
++        for(i=0; i < num_args; i++) {
++            apc_swizzle_ptr(bd, ll, &arg_info_array[i].name);
++            apc_swizzle_ptr(bd, ll, &arg_info_array[i].class_name);
++        }
 +    }
 +
-+    /* compile the expressions */
-+    for (i = 0; i < npat; i++) {
-+        char *pattern = patterns[i];
-+        if(pattern[0]=='+') { regs[i]->type = APC_POSITIVE_MATCH; pattern = patterns[i]+sizeof(char); }
-+        else if(pattern[0]=='-') { regs[i]->type = APC_NEGATIVE_MATCH; pattern = patterns[i]+sizeof(char); }
++} /* }}} */
++
++
++/* {{{ apc_swizzle_hashtable */
++static void apc_swizzle_hashtable(apc_bd_t *bd, zend_llist *ll, HashTable *ht, apc_swizzle_cb_t swizzle_cb, int is_ptr TSRMLS_DC) {
++    uint i;
++    Bucket **bp, **bp_prev;
++
++    bp = &ht->pListHead;
++    while(*bp) {
++        bp_prev = bp;
++        bp = &(*bp)->pListNext;
++        if(is_ptr) {
++            swizzle_cb(bd, ll, *(void**)(*bp_prev)->pData TSRMLS_CC);
++            apc_swizzle_ptr(bd, ll, (*bp_prev)->pData);
++        } else {
++            swizzle_cb(bd, ll, (void**)(*bp_prev)->pData TSRMLS_CC);
++        }
++        apc_swizzle_ptr(bd, ll, &(*bp_prev)->pData);
++        if((*bp_prev)->pDataPtr) {
++            apc_swizzle_ptr(bd, ll, &(*bp_prev)->pDataPtr);
++        }
++        if((*bp_prev)->pListLast) {
++            apc_swizzle_ptr(bd, ll, &(*bp_prev)->pListLast);
++        }
++        if((*bp_prev)->pNext) {
++            apc_swizzle_ptr(bd, ll, &(*bp_prev)->pNext);
++        }
++        if((*bp_prev)->pLast) {
++            apc_swizzle_ptr(bd, ll, &(*bp_prev)->pLast);
++        }
++        apc_swizzle_ptr(bd, ll, bp_prev);
++    }
++    for(i=0; i < ht->nTableSize; i++) {
++        if(ht->arBuckets[i]) {
++            apc_swizzle_ptr(bd, ll, &ht->arBuckets[i]);
++        }
++    }
++    apc_swizzle_ptr(bd, ll, &ht->pListTail);
 +
-+        regs[i]->reg = (regex_t*) apc_emalloc(sizeof(regex_t));
++    apc_swizzle_ptr(bd, ll, &ht->arBuckets);
++} /* }}} */
 +
-+        if (regcomp(regs[i]->reg, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
-+            apc_wprint("apc_regex_compile_array: invalid expression '%s'",
-+                       pattern);
 +
-+            apc_regex_destroy_array(regs);
++/* {{{ apc_swizzle_zval */
++static void apc_swizzle_zval(apc_bd_t *bd, zend_llist *ll, zval *zv TSRMLS_DC) {
 +
-+            return NULL;
++    if(APCG(copied_zvals).nTableSize) {
++        if(zend_hash_index_exists(&APCG(copied_zvals), (ulong)zv)) {
++          return;
 +        }
++        zend_hash_index_update(&APCG(copied_zvals), (ulong)zv, (void**)&zv, sizeof(zval*), NULL);
 +    }
 +
-+    return (void*) regs;
-+}
++    switch(zv->type & ~IS_CONSTANT_INDEX) {
++        case IS_NULL:
++        case IS_LONG:
++        case IS_DOUBLE:
++        case IS_BOOL:
++        case IS_RESOURCE:
++            /* nothing to do */
++            break;
++        case IS_CONSTANT:
++        case IS_STRING:
++            apc_swizzle_ptr(bd, ll, &zv->value.str.val);
++            break;
++        case IS_ARRAY:
++        case IS_CONSTANT_ARRAY:
++            apc_swizzle_hashtable(bd, ll, zv->value.ht, (apc_swizzle_cb_t)apc_swizzle_zval, 1 TSRMLS_CC);
++            apc_swizzle_ptr(bd, ll, &zv->value.ht);
++            break;
++        case IS_OBJECT:
++            break;
++        default:
++            assert(0); /* shouldn't happen */
++    }
++} /* }}} */
 +
-+void apc_regex_destroy_array(void* p)
-+{
-+    if (p != NULL) {
-+        apc_regex** regs = (apc_regex**) p;
-+        int i;
 +
-+        for (i = 0; regs[i]->reg != NULL; i++) {
-+            regfree(regs[i]->reg);
-+            apc_efree(regs[i]->reg);
-+            apc_efree(regs[i]);
++/* {{{ apc_swizzle_bd */
++static apc_bd_t* apc_swizzle_bd(apc_bd_t* bd, zend_llist *ll TSRMLS_DC) {
++    int count, i;
++    PHP_MD5_CTX context;
++    unsigned char digest[16];
++    register php_uint32 crc;
++    php_uint32 crcinit = 0;
++    char *crc_p;
++    void ***ptr;
++    void ***ptr_list;
++
++    count = zend_llist_count(ll);
++    ptr_list = emalloc(count * sizeof(void**));
++    ptr = zend_llist_get_first(ll);
++    for(i=0; i < count; i++) {
++#if APC_BINDUMP_DEBUG
++        printf("[%06d] ", i+1);
++#endif
++        SWIZZLE(bd, **ptr); /* swizzle ptr */
++        if((long)bd < (long)*ptr && (ulong)*ptr < ((long)bd + bd->size)) {  /* exclude ptrs that aren't actually included in the ptr list */
++#if APC_BINDUMP_DEBUG
++            printf("[------] ");
++#endif
++            SWIZZLE(bd, *ptr);  /* swizzle ptr list */
++            ptr_list[i] = *ptr;
 +        }
-+        apc_efree(regs);
++        ptr = zend_llist_get_next(ll);
 +    }
-+}
++    SWIZZLE(bd, bd->entries);
 +
-+int apc_regex_match_array(void* p, const char* input)
-+{
-+    apc_regex** regs;
++    if(count > 0) {
++        bd = erealloc(bd, bd->size + (count * sizeof(void**)));
++        bd->num_swizzled_ptrs = count;
++        bd->swizzled_ptrs = (void***)((unsigned char *)bd + bd->size -2);   /* extra -1 for null termination */
++        bd->size += count * sizeof(void**);
++        memcpy(bd->swizzled_ptrs, ptr_list, count * sizeof(void**));
++        SWIZZLE(bd, bd->swizzled_ptrs);
++    } else {
++        bd->num_swizzled_ptrs = 0;
++        bd->swizzled_ptrs = NULL;
++    }
++    ((char*)bd)[bd->size-1] = 0;  /* silence null termination for zval strings */
++    efree(ptr_list);
++    bd->swizzled = 1;
++
++    /* Generate MD5/CRC32 checksum */
++    for(i=0; i<16; i++) { bd->md5[i] = 0; }
++    bd->crc=0;
++    PHP_MD5Init(&context);
++    PHP_MD5Update(&context, (const unsigned char*)bd, bd->size);
++    PHP_MD5Final(digest, &context);
++    crc = crcinit^0xFFFFFFFF;
++    crc_p = (char*)bd;
++    for(i=bd->size; i--; ++crc_p) {
++      crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*crc_p)) & 0xFF ];
++    }
++    memcpy(bd->md5, digest, 16);
++    bd->crc = crc;
++
++    return bd;
++} /* }}} */
++
++
++/* {{{ apc_unswizzle_bd */
++static int apc_unswizzle_bd(apc_bd_t *bd, int flags TSRMLS_DC) {
 +    int i;
++    unsigned char md5_orig[16];
++    unsigned char digest[16];
++    PHP_MD5_CTX context;
++    register php_uint32 crc;
++    php_uint32 crcinit = 0;
++    php_uint32 crc_orig;
++    char *crc_p;
++
++    /* Verify the md5 or crc32 before we unswizzle */
++    memcpy(md5_orig, bd->md5, 16);
++    for(i=0; i<16; i++) { bd->md5[i] = 0; }
++    crc_orig = bd->crc;
++    bd->crc=0;
++    if(flags & APC_BIN_VERIFY_MD5) {
++        PHP_MD5Init(&context);
++        PHP_MD5Update(&context, (const unsigned char*)bd, bd->size);
++        PHP_MD5Final(digest, &context);
++        if(memcmp(md5_orig, digest, 16)) {
++            apc_eprint("MD5 checksum of binary dump failed.");
++            memcpy(bd->md5, md5_orig, 16); /* add back md5 checksum */
++            return -1;
++        }
++    }
++    if(flags & APC_BIN_VERIFY_CRC32) {
++        crc = crcinit^0xFFFFFFFF;
++        crc_p = (char*)bd;
++        for(i=bd->size; i--; ++crc_p) {
++          crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[(crc ^ (*crc_p)) & 0xFF ];
++        }
++        if(crc_orig != crc) {
++            apc_eprint("CRC32 checksum of binary dump failed.");
++            bd->crc = crc_orig;
++            return -1;
++        }
++    }
++    memcpy(bd->md5, md5_orig, 16); /* add back md5 checksum */
++    bd->crc = crc_orig;
 +
-+    if (!p)
-+        return 0;
++    UNSWIZZLE(bd, bd->entries);
++    UNSWIZZLE(bd, bd->swizzled_ptrs);
++    for(i=0; i < bd->num_swizzled_ptrs; i++) {
++        if(bd->swizzled_ptrs[i]) {
++            UNSWIZZLE(bd, bd->swizzled_ptrs[i]);
++            if(*bd->swizzled_ptrs[i] && (*bd->swizzled_ptrs[i] < (void*)bd)) {
++                UNSWIZZLE(bd, *bd->swizzled_ptrs[i]);
++            }
++        }
++    }
 +
-+    regs = (apc_regex**) p;
-+    for (i = 0; regs[i]->reg != NULL; i++)
-+        if (regexec(regs[i]->reg, input, 0, NULL, 0) == 0)
-+            return (int)(regs[i]->type);
++    bd->swizzled=0;
 +
 +    return 0;
-+}
++} /* }}} */
 +
-+/* }}} */
 +
-+/* {{{ crc32 implementation */
++/* {{{ apc_bin_checkfilter */
++static int apc_bin_checkfilter(HashTable *filter, const char *key, uint key_len) {
++    zval **zptr;
 +
-+/* this table was generated by crc32gen() */
-+static unsigned int crc32tab[] = {
-+    /*   0 */  0x00000000, 0x3b83984b, 0x77073096, 0x4c84a8dd, 
-+    /*   4 */  0xee0e612c, 0xd58df967, 0x990951ba, 0xa28ac9f1, 
-+    /*   8 */  0x076dc419, 0x3cee5c52, 0x706af48f, 0x4be96cc4, 
-+    /*  12 */  0xe963a535, 0xd2e03d7e, 0x9e6495a3, 0xa5e70de8, 
-+    /*  16 */  0x0edb8832, 0x35581079, 0x79dcb8a4, 0x425f20ef, 
-+    /*  20 */  0xe0d5e91e, 0xdb567155, 0x97d2d988, 0xac5141c3, 
-+    /*  24 */  0x09b64c2b, 0x3235d460, 0x7eb17cbd, 0x4532e4f6, 
-+    /*  28 */  0xe7b82d07, 0xdc3bb54c, 0x90bf1d91, 0xab3c85da, 
-+    /*  32 */  0x1db71064, 0x2634882f, 0x6ab020f2, 0x5133b8b9, 
-+    /*  36 */  0xf3b97148, 0xc83ae903, 0x84be41de, 0xbf3dd995, 
-+    /*  40 */  0x1adad47d, 0x21594c36, 0x6ddde4eb, 0x565e7ca0, 
-+    /*  44 */  0xf4d4b551, 0xcf572d1a, 0x83d385c7, 0xb8501d8c, 
-+    /*  48 */  0x136c9856, 0x28ef001d, 0x646ba8c0, 0x5fe8308b, 
-+    /*  52 */  0xfd62f97a, 0xc6e16131, 0x8a65c9ec, 0xb1e651a7, 
-+    /*  56 */  0x14015c4f, 0x2f82c404, 0x63066cd9, 0x5885f492, 
-+    /*  60 */  0xfa0f3d63, 0xc18ca528, 0x8d080df5, 0xb68b95be, 
-+    /*  64 */  0x3b6e20c8, 0x00edb883, 0x4c69105e, 0x77ea8815, 
-+    /*  68 */  0xd56041e4, 0xeee3d9af, 0xa2677172, 0x99e4e939, 
-+    /*  72 */  0x3c03e4d1, 0x07807c9a, 0x4b04d447, 0x70874c0c, 
-+    /*  76 */  0xd20d85fd, 0xe98e1db6, 0xa50ab56b, 0x9e892d20, 
-+    /*  80 */  0x35b5a8fa, 0x0e3630b1, 0x42b2986c, 0x79310027, 
-+    /*  84 */  0xdbbbc9d6, 0xe038519d, 0xacbcf940, 0x973f610b, 
-+    /*  88 */  0x32d86ce3, 0x095bf4a8, 0x45df5c75, 0x7e5cc43e, 
-+    /*  92 */  0xdcd60dcf, 0xe7559584, 0xabd13d59, 0x9052a512, 
-+    /*  96 */  0x26d930ac, 0x1d5aa8e7, 0x51de003a, 0x6a5d9871, 
-+    /* 100 */  0xc8d75180, 0xf354c9cb, 0xbfd06116, 0x8453f95d, 
-+    /* 104 */  0x21b4f4b5, 0x1a376cfe, 0x56b3c423, 0x6d305c68, 
-+    /* 108 */  0xcfba9599, 0xf4390dd2, 0xb8bda50f, 0x833e3d44, 
-+    /* 112 */  0x2802b89e, 0x138120d5, 0x5f058808, 0x64861043, 
-+    /* 116 */  0xc60cd9b2, 0xfd8f41f9, 0xb10be924, 0x8a88716f, 
-+    /* 120 */  0x2f6f7c87, 0x14ece4cc, 0x58684c11, 0x63ebd45a, 
-+    /* 124 */  0xc1611dab, 0xfae285e0, 0xb6662d3d, 0x8de5b576, 
-+    /* 128 */  0x76dc4190, 0x4d5fd9db, 0x01db7106, 0x3a58e94d, 
-+    /* 132 */  0x98d220bc, 0xa351b8f7, 0xefd5102a, 0xd4568861, 
-+    /* 136 */  0x71b18589, 0x4a321dc2, 0x06b6b51f, 0x3d352d54, 
-+    /* 140 */  0x9fbfe4a5, 0xa43c7cee, 0xe8b8d433, 0xd33b4c78, 
-+    /* 144 */  0x7807c9a2, 0x438451e9, 0x0f00f934, 0x3483617f, 
-+    /* 148 */  0x9609a88e, 0xad8a30c5, 0xe10e9818, 0xda8d0053, 
-+    /* 152 */  0x7f6a0dbb, 0x44e995f0, 0x086d3d2d, 0x33eea566, 
-+    /* 156 */  0x91646c97, 0xaae7f4dc, 0xe6635c01, 0xdde0c44a, 
-+    /* 160 */  0x6b6b51f4, 0x50e8c9bf, 0x1c6c6162, 0x27eff929, 
-+    /* 164 */  0x856530d8, 0xbee6a893, 0xf262004e, 0xc9e19805, 
-+    /* 168 */  0x6c0695ed, 0x57850da6, 0x1b01a57b, 0x20823d30, 
-+    /* 172 */  0x8208f4c1, 0xb98b6c8a, 0xf50fc457, 0xce8c5c1c, 
-+    /* 176 */  0x65b0d9c6, 0x5e33418d, 0x12b7e950, 0x2934711b, 
-+    /* 180 */  0x8bbeb8ea, 0xb03d20a1, 0xfcb9887c, 0xc73a1037, 
-+    /* 184 */  0x62dd1ddf, 0x595e8594, 0x15da2d49, 0x2e59b502, 
-+    /* 188 */  0x8cd37cf3, 0xb750e4b8, 0xfbd44c65, 0xc057d42e, 
-+    /* 192 */  0x4db26158, 0x7631f913, 0x3ab551ce, 0x0136c985, 
-+    /* 196 */  0xa3bc0074, 0x983f983f, 0xd4bb30e2, 0xef38a8a9, 
-+    /* 200 */  0x4adfa541, 0x715c3d0a, 0x3dd895d7, 0x065b0d9c, 
-+    /* 204 */  0xa4d1c46d, 0x9f525c26, 0xd3d6f4fb, 0xe8556cb0, 
-+    /* 208 */  0x4369e96a, 0x78ea7121, 0x346ed9fc, 0x0fed41b7, 
-+    /* 212 */  0xad678846, 0x96e4100d, 0xda60b8d0, 0xe1e3209b, 
-+    /* 216 */  0x44042d73, 0x7f87b538, 0x33031de5, 0x088085ae, 
-+    /* 220 */  0xaa0a4c5f, 0x9189d414, 0xdd0d7cc9, 0xe68ee482, 
-+    /* 224 */  0x5005713c, 0x6b86e977, 0x270241aa, 0x1c81d9e1, 
-+    /* 228 */  0xbe0b1010, 0x8588885b, 0xc90c2086, 0xf28fb8cd, 
-+    /* 232 */  0x5768b525, 0x6ceb2d6e, 0x206f85b3, 0x1bec1df8, 
-+    /* 236 */  0xb966d409, 0x82e54c42, 0xce61e49f, 0xf5e27cd4, 
-+    /* 240 */  0x5edef90e, 0x655d6145, 0x29d9c998, 0x125a51d3, 
-+    /* 244 */  0xb0d09822, 0x8b530069, 0xc7d7a8b4, 0xfc5430ff, 
-+    /* 248 */  0x59b33d17, 0x6230a55c, 0x2eb40d81, 0x153795ca, 
-+    /* 252 */  0xb7bd5c3b, 0x8c3ec470, 0xc0ba6cad, 0xfb39f4e6, 
-+};
++    if(filter == NULL) {
++        return 1;
++    }
 +
-+unsigned int apc_crc32(const char* buf, int len)
-+{
-+    int i;
-+    int k;
-+    unsigned int crc;
++    if(zend_hash_find(filter, (char*)key, key_len, (void**)&zptr) == SUCCESS) {
++        if(Z_TYPE_PP(zptr) == IS_LONG && Z_LVAL_PP(zptr) == 0) {
++            return 0;
++        }
++    } else {
++        return 0;
++    }
 +
-+    /* preconditioning */
-+    crc = 0xFFFFFFFF;
-+    
-+    for (i = 0; i < len; i++) {
-+        k = (crc ^ buf[i]) & 0x000000FF;
-+        crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[k];
++
++    return 1;
++} /* }}} */
++
++/* {{{ apc_bin_fixup_op_array */
++static inline void apc_bin_fixup_op_array(zend_op_array *op_array) {
++    ulong i;
++    for (i = 0; i < op_array->last; i++) {
++        op_array->opcodes[i].handler = zend_opcode_handlers[APC_OPCODE_HANDLER_DECODE(&op_array->opcodes[i])];
 +    }
++}
++/* }}} */
 +
-+    /* postconditioning */
-+    return ~crc;
++/* {{{ apc_bin_fixup_class_entry */
++static inline void apc_bin_fixup_class_entry(zend_class_entry *ce) {
++    zend_function *fe;
++    HashPosition hpos;
++
++    /* fixup the opcodes in each method */
++    zend_hash_internal_pointer_reset_ex(&ce->function_table, &hpos);
++    while(zend_hash_get_current_data_ex(&ce->function_table, (void**)&fe, &hpos) == SUCCESS) {
++        apc_bin_fixup_op_array(&fe->op_array);
++        zend_hash_move_forward_ex(&ce->function_table, &hpos);
++    }
++
++    /* fixup hashtable destructor pointers */
++    ce->function_table.pDestructor = (dtor_func_t)zend_function_dtor;
++    ce->default_properties.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
++    ce->properties_info.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
++    ce->default_static_members.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
++    if (ce->static_members) {
++        ce->static_members->pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
++    }
++    ce->constants_table.pDestructor = (dtor_func_t)zval_ptr_dtor_wrapper;
 +}
++/* }}} */
++
++/* {{{ apc_bin_dump */
++apc_bd_t* apc_bin_dump(HashTable *files, HashTable *user_vars TSRMLS_DC) {
 +
-+/* crc32gen: generate the nth (0..255) crc32 table value */
-+#if 0
-+static unsigned long crc32gen(int n)
-+{
 +    int i;
-+    unsigned long crc;
-+    
-+    crc = n;
-+    for (i = 8; i >= 0; i--) {
-+        if (crc & 1) {
-+            crc = (crc >> 1) ^ 0xEDB88320;
++    uint fcount;
++    slot_t *sp;
++    apc_bd_entry_t *ep;
++    int count=0;
++    apc_bd_t *bd;
++    zend_llist ll;
++    zend_function *efp, *sfp;
++    long size=0;
++    apc_context_t ctxt;
++    void *pool_ptr;
++
++    zend_llist_init(&ll, sizeof(void*), NULL, 0);
++    zend_hash_init(&APCG(apc_bd_alloc_list), 0, NULL, NULL, 0);
++
++    /* flip the hash for faster filter checking */
++    files = apc_flip_hash(files);
++    user_vars = apc_flip_hash(user_vars);
++
++    /* get size and entry counts */
++    for(i=0; i < apc_user_cache->num_slots; i++) {
++        sp = apc_user_cache->slots[i];
++        for(; sp != NULL; sp = sp->next) {
++            if(apc_bin_checkfilter(user_vars, sp->key.data.user.identifier, sp->key.data.user.identifier_len+1)) {
++                size += sizeof(apc_bd_entry_t*) + sizeof(apc_bd_entry_t);
++                size += sp->value->mem_size - (sizeof(apc_cache_entry_t) - sizeof(apc_cache_entry_value_t));
++                count++;
++            }
 +        }
-+        else {
-+            crc >>= 1;
++    }
++    for(i=0; i < apc_cache->num_slots; i++) {
++        sp = apc_cache->slots[i];
++        for(; sp != NULL; sp = sp->next) {
++            if(sp->key.type == APC_CACHE_KEY_FPFILE) {
++                if(apc_bin_checkfilter(files, sp->key.data.fpfile.fullpath, sp->key.data.fpfile.fullpath_len+1)) {
++                    size += sizeof(apc_bd_entry_t*) + sizeof(apc_bd_entry_t);
++                    size += sp->value->mem_size - (sizeof(apc_cache_entry_t) - sizeof(apc_cache_entry_value_t));
++                    count++;
++                }
++            } else {
++                /* TODO: Currently we don't support APC_CACHE_KEY_FILE type.  We need to store the path and re-stat on load */
++                apc_wprint("Excluding some files from apc_bin_dump[file].  Cached files must be included using full path with apc.stat=0.");
++            }
 +        }
 +    }
-+    return crc;
-+}
++
++    size += sizeof(apc_bd_t) +1;  /* +1 for null termination */
++    bd = emalloc(size);
++    bd->size = size;
++    pool_ptr = emalloc(sizeof(apc_pool));
++    apc_bd_alloc_ex(pool_ptr, sizeof(apc_pool));
++    ctxt.pool = apc_pool_create(APC_UNPOOL, apc_bd_alloc, apc_bd_free, NULL, NULL);  /* ideally the pool wouldn't be alloc'd as part of this */
++    if (!ctxt.pool) { /* TODO need to cleanup */
++        apc_wprint("Unable to allocate memory for pool.");
++        return NULL;
++    }
++    ctxt.copy = APC_COPY_IN_USER;  /* avoid stupid ALLOC_ZVAL calls here, hack */
++    apc_bd_alloc_ex( (void*)((long)bd + sizeof(apc_bd_t)), bd->size - sizeof(apc_bd_t) -1);
++    bd->num_entries = count;
++    bd->entries = apc_bd_alloc_ex(NULL, sizeof(apc_bd_entry_t) * count);
++
++    /* User entries */
++    zend_hash_init(&APCG(copied_zvals), 0, NULL, NULL, 0);
++    count = 0;
++    for(i=0; i < apc_user_cache->num_slots; i++) {
++        sp = apc_user_cache->slots[i];
++        for(; sp != NULL; sp = sp->next) {
++            if(apc_bin_checkfilter(user_vars, sp->key.data.user.identifier, sp->key.data.user.identifier_len+1)) {
++                ep = &bd->entries[count];
++                ep->type = sp->value->type;
++                ep->val.user.info = apc_bd_alloc(sp->value->data.user.info_len+1);
++                memcpy(ep->val.user.info, sp->value->data.user.info, sp->value->data.user.info_len+1);
++                ep->val.user.info_len = sp->value->data.user.info_len;
++                ep->val.user.val = apc_copy_zval(NULL, sp->value->data.user.val, &ctxt);
++                ep->val.user.ttl = sp->value->data.user.ttl;
++
++                /* swizzle pointers */
++                apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.user.info);
++                zend_hash_clean(&APCG(copied_zvals));
++                apc_swizzle_zval(bd, &ll, bd->entries[count].val.user.val TSRMLS_CC);
++                apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.user.val);
++
++                count++;
++            }
++        }
++    }
++    zend_hash_destroy(&APCG(copied_zvals));
++    APCG(copied_zvals).nTableSize=0;
++
++    /* File entries */
++    for(i=0; i < apc_cache->num_slots; i++) {
++        for(sp=apc_cache->slots[i]; sp != NULL; sp = sp->next) {
++            if(sp->key.type == APC_CACHE_KEY_FPFILE) {
++                if(apc_bin_checkfilter(files, sp->key.data.fpfile.fullpath, sp->key.data.fpfile.fullpath_len+1)) {
++                    ep = &bd->entries[count];
++                    ep->type = sp->key.type;
++                    ep->val.file.filename = apc_bd_alloc(strlen(sp->value->data.file.filename)+1);
++                    strcpy(ep->val.file.filename, sp->value->data.file.filename);
++                    ep->val.file.op_array = apc_copy_op_array(NULL, sp->value->data.file.op_array, &ctxt TSRMLS_CC);
++
++                    for(ep->num_functions=0; sp->value->data.file.functions[ep->num_functions].function != NULL;) { ep->num_functions++; }
++                    ep->val.file.functions = apc_bd_alloc(sizeof(apc_function_t) * ep->num_functions);
++                    for(fcount=0; fcount < ep->num_functions; fcount++) {
++                        memcpy(&ep->val.file.functions[fcount], &sp->value->data.file.functions[fcount], sizeof(apc_function_t));
++                        ep->val.file.functions[fcount].name = apc_xmemcpy(sp->value->data.file.functions[fcount].name, sp->value->data.file.functions[fcount].name_len+1, apc_bd_alloc);
++                        ep->val.file.functions[fcount].name_len = sp->value->data.file.functions[fcount].name_len;
++                        ep->val.file.functions[fcount].function = apc_bd_alloc(sizeof(zend_function));
++                        efp = ep->val.file.functions[fcount].function;
++                        sfp = sp->value->data.file.functions[fcount].function;
++                        switch(sfp->type) {
++                            case ZEND_INTERNAL_FUNCTION:
++                            case ZEND_OVERLOADED_FUNCTION:
++                                efp->op_array = sfp->op_array;
++                                break;
++                            case ZEND_USER_FUNCTION:
++                            case ZEND_EVAL_CODE:
++                                apc_copy_op_array(&efp->op_array, &sfp->op_array, &ctxt TSRMLS_CC);
++                                break;
++                            default:
++                                assert(0);
++                        }
++#ifdef ZEND_ENGINE_2
++                        efp->common.prototype = NULL;
++                        efp->common.fn_flags = sfp->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
 +#endif
++                        apc_swizzle_ptr(bd, &ll, &ep->val.file.functions[fcount].name);
++                        apc_swizzle_ptr(bd, &ll, (void**)&ep->val.file.functions[fcount].function);
++                        apc_swizzle_op_array(bd, &ll, &efp->op_array TSRMLS_CC);
++                    }
 +
-+/* }}} */
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_cache.c php-5.2.5/ext/apc/apc_cache.c
---- php-5.2.5-orig/ext/apc/apc_cache.c 1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_cache.c      2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,1343 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
-+  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
-+  +----------------------------------------------------------------------+
++                    for(ep->num_classes=0; sp->value->data.file.classes[ep->num_classes].class_entry != NULL;) { ep->num_classes++; }
++                    ep->val.file.classes = apc_bd_alloc(sizeof(apc_class_t) * ep->num_classes);
++                    for(fcount=0; fcount < ep->num_classes; fcount++) {
++                        ep->val.file.classes[fcount].name = apc_xmemcpy(sp->value->data.file.classes[fcount].name, sp->value->data.file.classes[fcount].name_len+1, apc_bd_alloc);
++                        ep->val.file.classes[fcount].name_len = sp->value->data.file.classes[fcount].name_len;
++                        ep->val.file.classes[fcount].class_entry = apc_copy_class_entry(NULL, sp->value->data.file.classes[fcount].class_entry, &ctxt);
++                        ep->val.file.classes[fcount].parent_name = apc_xstrdup(sp->value->data.file.classes[fcount].parent_name, apc_bd_alloc);
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++                        apc_swizzle_ptr(bd, &ll, &ep->val.file.classes[fcount].name);
++                        apc_swizzle_ptr(bd, &ll, &ep->val.file.classes[fcount].parent_name);
++                        apc_swizzle_class_entry(bd, &ll, ep->val.file.classes[fcount].class_entry TSRMLS_CC);
++                        apc_swizzle_ptr(bd, &ll, &ep->val.file.classes[fcount].class_entry);
++                    }
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++                    apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.file.filename);
++                    apc_swizzle_op_array(bd, &ll, bd->entries[count].val.file.op_array TSRMLS_CC);
++                    apc_swizzle_ptr(bd, &ll, &bd->entries[count].val.file.op_array);
++                    apc_swizzle_ptr(bd, &ll, (void**)&ep->val.file.functions);
++                    apc_swizzle_ptr(bd, &ll, (void**)&ep->val.file.classes);
 +
-+ */
++                    count++;
++                } else {
++                    /* TODO: Currently we don't support APC_CACHE_KEY_FILE type.  We need to store the path and re-stat on load */
++                }
++            }
++        }
++    }
 +
-+/* $Id: apc_cache.c,v 3.145 2007/10/05 23:06:56 gopalv Exp $ */
++    /* append swizzle pointer list to bd */
++    bd = apc_swizzle_bd(bd, &ll TSRMLS_CC);
++    zend_llist_destroy(&ll);
++    zend_hash_destroy(&APCG(apc_bd_alloc_list));
 +
-+#include "apc_cache.h"
-+#include "apc_lock.h"
-+#include "apc_sma.h"
-+#include "apc_globals.h"
-+#include "SAPI.h"
-+#include "ext/standard/php_var.h"
-+#include "ext/standard/php_smart_str.h"
++    if(files) {
++        zend_hash_destroy(files);
++        efree(files);
++    }
++    if(user_vars) {
++        zend_hash_destroy(user_vars);
++        efree(user_vars);
++    }
 +
-+/* TODO: rehash when load factor exceeds threshold */
++    efree(pool_ptr);
 +
-+#define CHECK(p) { if ((p) == NULL) return NULL; }
++    return bd;
++} /* }}} */
 +
-+/* {{{ locking macros */
-+#define CREATE_LOCK(lock)     apc_lck_create(NULL, 0, 1, lock)
-+#define DESTROY_LOCK(c) apc_lck_destroy(c->header->lock)
-+#define LOCK(c)         { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(c->header->lock); }
-+#define RDLOCK(c)       { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(c->header->lock); }
-+#define UNLOCK(c)       { apc_lck_unlock(c->header->lock); HANDLE_UNBLOCK_INTERRUPTIONS(); }
-+/* }}} */
 +
-+/* {{{ struct definition: slot_t */
-+typedef struct slot_t slot_t;
-+struct slot_t {
-+    apc_cache_key_t key;        /* slot key */
-+    apc_cache_entry_t* value;   /* slot value */
-+    slot_t* next;               /* next slot in linked list */
-+    int num_hits;               /* number of hits to this bucket */
-+    time_t creation_time;       /* time slot was initialized */
-+    time_t deletion_time;       /* time slot was removed from cache */
-+    time_t access_time;         /* time slot was last accessed */
-+};
-+/* }}} */
++/* {{{ apc_bin_load */
++int apc_bin_load(apc_bd_t *bd, int flags TSRMLS_DC) {
 +
-+/* {{{ struct definition: header_t
-+   Any values that must be shared among processes should go in here. */
-+typedef struct header_t header_t;
-+struct header_t {
-+    apc_lck_t lock;              /* read/write lock (exclusive blocking cache lock) */
-+    apc_lck_t wrlock;           /* write lock (non-blocking used to prevent cache slams) */
-+    int num_hits;               /* total successful hits in cache */
-+    int num_misses;             /* total unsuccessful hits in cache */
-+    int num_inserts;            /* total successful inserts in cache */
-+    slot_t* deleted_list;       /* linked list of to-be-deleted slots */
-+    time_t start_time;          /* time the above counters were reset */
-+    int expunges;               /* total number of expunges */
-+    zend_bool busy;             /* Flag to tell clients when we are busy cleaning the cache */
-+    int num_entries;            /* Statistic on the number of entries */
-+    size_t mem_size;            /* Statistic on the memory size used by this cache */
-+};
-+/* }}} */
++    apc_bd_entry_t *ep;
++    uint i, i2;
++    int ret;
++    time_t t;
++    zend_op_array *alloc_op_array = NULL;
++    apc_function_t *alloc_functions = NULL;
++    apc_class_t *alloc_classes = NULL;
++    apc_cache_entry_t *cache_entry;
++    apc_cache_key_t cache_key;
++    apc_context_t ctxt;
++
++    if (bd->swizzled) {
++        if(apc_unswizzle_bd(bd, flags TSRMLS_CC) < 0) {
++            return -1;
++        }
++    }
 +
-+/* {{{ struct definition: apc_cache_t */
-+struct apc_cache_t {
-+    void* shmaddr;              /* process (local) address of shared cache */
-+    header_t* header;           /* cache header (stored in SHM) */
-+    slot_t** slots;             /* array of cache slots (stored in SHM) */
-+    int num_slots;              /* number of slots in cache */
-+    int gc_ttl;                 /* maximum time on GC list for a slot */
-+    int ttl;                    /* if slot is needed and entry's access time is older than this ttl, remove it */
-+};
-+/* }}} */
++    t = apc_time();
 +
-+/* {{{ struct definition local_slot_t */
-+typedef struct local_slot_t local_slot_t;
-+struct local_slot_t {
-+    slot_t *original;           /* the original slot in shm */
-+    int num_hits;               /* number of hits */
-+    time_t creation_time;       /* creation time */
-+    apc_cache_entry_t *value;   /* shallow copy of slot->value */
-+    local_slot_t *next;         /* only for dead list */
-+};
-+/* }}} */
-+/* {{{ struct definition apc_local_cache_t */
-+struct apc_local_cache_t {
-+    apc_cache_t* shmcache;      /* the real cache in shm */
-+    local_slot_t* slots;        /* process (local) cache of objects */
-+    local_slot_t* dead_list;    /* list of objects pending removal */
-+    int num_slots;              /* number of slots in cache */
-+    int ttl;                    /* time to live */
-+    int num_hits;               /* number of hits */
-+    int generation;             /* every generation lives between expunges */
-+};
-+/* }}} */
++    for(i = 0; i < bd->num_entries; i++) {
++        ctxt.pool = apc_pool_create(APC_SMALL_POOL, apc_sma_malloc, apc_sma_free, apc_sma_protect, apc_sma_unprotect);
++        if (!ctxt.pool) { /* TODO need to cleanup previous pools */
++            apc_wprint("Unable to allocate memory for pool.");
++            goto failure;
++        }
++        ep = &bd->entries[i];
++        switch (ep->type) {
++            case APC_CACHE_KEY_FILE:
++                /* TODO: Currently we don't support APC_CACHE_KEY_FILE type.  We need to store the path and re-stat on load (or something else perhaps?) */
++                break;
++            case APC_CACHE_KEY_FPFILE:
++                ctxt.copy = APC_COPY_IN_OPCODE;
 +
-+/* {{{ key_equals */
-+#define key_equals(a, b) (a.inode==b.inode && a.device==b.device)
-+/* }}} */
++                HANDLE_BLOCK_INTERRUPTIONS();
++#if NONBLOCKING_LOCK_AVAILABLE
++                if(APCG(write_lock)) {
++                    if(!apc_cache_write_lock(apc_cache)) {
++                        HANDLE_UNBLOCK_INTERRUPTIONS();
++                        return -1;
++                    }
++                }
++#endif
++                if(! (alloc_op_array = apc_copy_op_array(NULL, ep->val.file.op_array, &ctxt TSRMLS_CC))) {
++                    goto failure;
++                }
++                apc_bin_fixup_op_array(alloc_op_array);
 +
-+/* {{{ hash */
-+static unsigned int hash(apc_cache_key_t key)
-+{
-+    return key.data.file.device + key.data.file.inode;
-+}
-+/* }}} */
++                if(! (alloc_functions = apc_sma_malloc(sizeof(apc_function_t) * (ep->num_functions + 1)))) {
++                    goto failure;
++                }
++                for(i2=0; i2 < ep->num_functions; i2++) {
++                    if(! (alloc_functions[i2].name = apc_xmemcpy(ep->val.file.functions[i2].name, ep->val.file.functions[i2].name_len+1, apc_sma_malloc))) {
++                        goto failure;
++                    }
++                    alloc_functions[i2].name_len = ep->val.file.functions[i2].name_len;
++                    if(! (alloc_functions[i2].function = apc_sma_malloc(sizeof(zend_function)))) {
++                        goto failure;
++                    }
++                    switch(ep->val.file.functions[i2].function->type) {
++                        case ZEND_INTERNAL_FUNCTION:
++                        case ZEND_OVERLOADED_FUNCTION:
++                            alloc_functions[i2].function->op_array = ep->val.file.functions[i2].function->op_array;
++                            break;
++                        case ZEND_USER_FUNCTION:
++                        case ZEND_EVAL_CODE:
++                            if (!apc_copy_op_array(&alloc_functions[i2].function->op_array, &ep->val.file.functions[i2].function->op_array, &ctxt TSRMLS_CC)) {
++                                goto failure;
++                            }
++                            apc_bin_fixup_op_array(&alloc_functions[i2].function->op_array);
++                            break;
++                        default:
++                            assert(0);
++                    }
++#ifdef ZEND_ENGINE_2
++                    alloc_functions[i2].function->common.prototype=NULL;
++                    alloc_functions[i2].function->common.fn_flags=ep->val.file.functions[i2].function->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
++#endif
++                }
++                alloc_functions[i2].name = NULL;
++                alloc_functions[i2].function = NULL;
 +
-+/* {{{ string_nhash_8 */
-+static unsigned int string_nhash_8(const char *s, size_t len)
-+{
-+    register const unsigned int *iv = (const unsigned int *)s;
-+    register unsigned int h = 0;
-+    register const unsigned int *e  = (const unsigned int *)(s + len - (len % sizeof(unsigned int)));
++                if(! (alloc_classes = apc_sma_malloc(sizeof(apc_class_t) * (ep->num_classes + 1)))) {
++                    goto failure;
++                }
++                for(i2=0; i2 < ep->num_classes; i2++) {
++                    if(! (alloc_classes[i2].name = apc_xmemcpy(ep->val.file.classes[i2].name, ep->val.file.classes[i2].name_len+1, apc_sma_malloc))) {
++                        goto failure;
++                    }
++                    alloc_classes[i2].name_len = ep->val.file.classes[i2].name_len;
++                    if(! (alloc_classes[i2].class_entry = apc_copy_class_entry(NULL, ep->val.file.classes[i2].class_entry, &ctxt))) {
++                        goto failure;
++                    }
++                    apc_bin_fixup_class_entry(alloc_classes[i2].class_entry);
++                    if(! (alloc_classes[i2].parent_name = apc_xstrdup(ep->val.file.classes[i2].parent_name, apc_sma_malloc))) {
++                        if(ep->val.file.classes[i2].parent_name != NULL) {
++                            goto failure;
++                        }
++                    }
++                }
++                alloc_classes[i2].name = NULL;
++                alloc_classes[i2].class_entry = NULL;
++
++                if(!(cache_entry = apc_cache_make_file_entry(ep->val.file.filename, alloc_op_array, alloc_functions, alloc_classes, &ctxt))) {
++                    goto failure;
++                }
++
++                if (!apc_cache_make_file_key(&cache_key, ep->val.file.filename, PG(include_path), t TSRMLS_CC)) {
++                    goto failure;
++                }
++
++                if ((ret = apc_cache_insert(apc_cache, cache_key, cache_entry, &ctxt, t)) != 1) {
++                    if(ret==-1) {
++                        goto failure;
++                    }
++                }
++
++#if NONBLOCKING_LOCK_AVAILABLE
++                if(APCG(write_lock)) {
++                    apc_cache_write_unlock(apc_cache);
++                }
++#endif
++                HANDLE_UNBLOCK_INTERRUPTIONS();
 +
-+    for(;iv<e;iv++) {
-+        h += *iv;
-+        h = (h << 7) | (h >> ((8*sizeof(unsigned int)) - 7));
++                break;
++            case APC_CACHE_KEY_USER:
++                ctxt.copy = APC_COPY_IN_USER;
++                _apc_store(ep->val.user.info, ep->val.user.info_len, ep->val.user.val, ep->val.user.ttl, 0 TSRMLS_CC);
++                break;
++            default:
++                break;
++       }
 +    }
-+    s = (const char *)iv;
-+    for(len %= sizeof(unsigned int);len;len--) {
-+        h += *(s++);
++
++    return 0;
++
++failure:
++    apc_pool_destroy(ctxt.pool);
++    apc_wprint("Unable to allocate memory for apc binary load/dump functionality.");
++#if NONBLOCKING_LOCK_AVAILABLE
++    if(APCG(write_lock)) {
++        apc_cache_write_unlock(apc_cache);
 +    }
-+    h ^= (h >> 13);
-+    h ^= (h >> 7);
-+    return h;
-+}
-+/* }}} */
++#endif
++    HANDLE_UNBLOCK_INTERRUPTIONS();
++    return -1;
++} /* }}} */
 +
-+/* {{{ make_slot */
-+slot_t* make_slot(apc_cache_key_t key, apc_cache_entry_t* value, slot_t* next, time_t t)
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_bin.h php-5.3.1/ext/apc/apc_bin.h
+--- php-5.3.1.orig/ext/apc/apc_bin.h   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_bin.h        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,63 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2009 The PHP Group                                     |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Brian Shire <shire@php.net>                                 |
++  +----------------------------------------------------------------------+
++
++ */
++
++/* $Id: apc_bin.h 274613 2009-01-26 06:57:57Z shire $ */
++
++#ifndef APC_BINDUMP_H
++#define APC_BINDUMP_H
++
++#include "apc.h"
++#include "apc_php.h"
++#include "ext/standard/basic_functions.h"
++
++/* APC binload flags */
++#define APC_BIN_VERIFY_MD5    1 << 0
++#define APC_BIN_VERIFY_CRC32  1 << 1
++
++typedef struct _apc_bd_entry_t {
++    unsigned char type;
++    uint num_functions;
++    uint num_classes;
++    apc_cache_entry_value_t val;
++} apc_bd_entry_t;
++
++typedef struct _apc_bd_t {
++    unsigned int size;
++    int swizzled;
++    unsigned char md5[16];
++    php_uint32 crc;
++    unsigned int num_entries;
++    apc_bd_entry_t *entries;
++    int num_swizzled_ptrs;
++    void ***swizzled_ptrs;
++} apc_bd_t;
++
++apc_bd_t* apc_bin_dump(HashTable *files, HashTable *user_vars TSRMLS_DC);
++int apc_bin_load(apc_bd_t *bd, int flags TSRMLS_DC);
++
++#endif
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc.c php-5.3.1/ext/apc/apc.c
+--- php-5.3.1.orig/ext/apc/apc.c       1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc.c    1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,635 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          George Schlossnagle <george@omniti.com>                     |
++  |          Rasmus Lerdorf <rasmus@php.net>                             |
++  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
++  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
++  +----------------------------------------------------------------------+
++
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
++
++   All other licensing and usage conditions are those of the PHP Group.
++
++ */
++
++/* $Id: apc.c 277132 2009-03-14 01:50:57Z shire $ */
++
++#include "apc.h"
++#include "apc_zend.h"
++#include "php.h"
++
++#if HAVE_PCRE || HAVE_BUNDLED_PCRE
++/*  Deal with problem present until php-5.2.2 where php_pcre.h was not installed correctly */
++#   if !HAVE_BUNDLED_PCRE && PHP_MAJOR_VERSION == 5 && (PHP_MINOR_VERSION < 2 || (PHP_MINOR_VERSION == 2 && PHP_RELEASE_VERSION < 2))
++#       include "apc_php_pcre.h"
++#   else
++#       include "ext/pcre/php_pcre.h"
++#   endif
++#   include "ext/standard/php_smart_str.h"
++#endif
++
++#define NELEMS(a) (sizeof(a)/sizeof((a)[0]))
++
++/* {{{ memory allocation wrappers */
++
++void* apc_emalloc(size_t n)
 +{
-+    slot_t* p = apc_sma_malloc(sizeof(slot_t));
-+    if (!p) return NULL;
++    void* p = malloc(n);
++    if (p == NULL) {
++        apc_eprint("apc_emalloc: malloc failed to allocate %u bytes:", n);
++    }
++    return p;
++}
 +
-+    if(value->type == APC_CACHE_ENTRY_USER) {
-+        char *identifier = (char*) apc_xstrdup(key.data.user.identifier, apc_sma_malloc);
-+        if (!identifier) {
-+            apc_sma_free(p);
-+            return NULL;
-+        }
-+        key.data.user.identifier = identifier;
-+    } else if(key.type == APC_CACHE_KEY_FPFILE) {
-+        char *fullpath = (char*) apc_xstrdup(key.data.fpfile.fullpath, apc_sma_malloc);
-+        if (!fullpath) {
-+            apc_sma_free(p);
-+            return NULL;
-+        }
-+        key.data.fpfile.fullpath = fullpath;
++void* apc_erealloc(void* p, size_t n)
++{
++    p = realloc(p, n);
++    if (p == NULL) {
++        apc_eprint("apc_erealloc: realloc failed to allocate %u bytes:", n);
 +    }
-+    p->key = key;
-+    p->value = value;
-+    p->next = next;
-+    p->num_hits = 0;
-+    p->creation_time = t;
-+    p->access_time = t;
-+    p->deletion_time = 0;
 +    return p;
 +}
-+/* }}} */
 +
-+/* {{{ free_slot */
-+static void free_slot(slot_t* slot)
++void apc_efree(void* p)
 +{
-+    if(slot->value->type == APC_CACHE_ENTRY_USER) {
-+        apc_sma_free((char *)slot->key.data.user.identifier);
-+    } else if(slot->key.type == APC_CACHE_KEY_FPFILE) {
-+        apc_sma_free((char *)slot->key.data.fpfile.fullpath);
++    if (p == NULL) {
++        apc_eprint("apc_efree: attempt to free null pointer");
 +    }
-+    apc_cache_free_entry(slot->value);
-+    apc_sma_free(slot);
++    free(p);
 +}
-+/* }}} */
 +
-+/* {{{ remove_slot */
-+static void remove_slot(apc_cache_t* cache, slot_t** slot)
++char* apc_estrdup(const char* s)
 +{
-+    slot_t* dead = *slot;
-+    *slot = (*slot)->next;
++    int len;
++    char* dup;
 +
-+    cache->header->mem_size -= dead->value->mem_size;
-+    cache->header->num_entries--;
-+    if (dead->value->ref_count <= 0) {
-+        free_slot(dead);
++    if (s == NULL) {
++        return NULL;
 +    }
-+    else {
-+        dead->next = cache->header->deleted_list;
-+        dead->deletion_time = time(0);
-+        cache->header->deleted_list = dead;
++    len = strlen(s);
++    dup = (char*) malloc(len+1);
++    if (dup == NULL) {
++        apc_eprint("apc_estrdup: malloc failed to allocate %u bytes:", len+1);
 +    }
++    memcpy(dup, s, len);
++    dup[len] = '\0';
++    return dup;
 +}
-+/* }}} */
 +
-+/* {{{ process_pending_removals */
-+static void process_pending_removals(apc_cache_t* cache)
++void* apc_xstrdup(const char* s, apc_malloc_t f)
 +{
-+    slot_t** slot;
-+    time_t now;
-+
-+    /* This function scans the list of removed cache entries and deletes any
-+     * entry whose reference count is zero (indicating that it is no longer
-+     * being executed) or that has been on the pending list for more than
-+     * cache->gc_ttl seconds (we issue a warning in the latter case).
-+     */
-+
-+    if (!cache->header->deleted_list)
-+        return;
++    return s != NULL ? apc_xmemcpy(s, strlen(s)+1, f) : NULL;
++}
 +
-+    slot = &cache->header->deleted_list;
-+    now = time(0);
++void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f)
++{
++    void* q;
 +
-+    while (*slot != NULL) {
-+        int gc_sec = cache->gc_ttl ? (now - (*slot)->deletion_time) : 0;
-+
-+        if ((*slot)->value->ref_count <= 0 || gc_sec > cache->gc_ttl) {
-+            slot_t* dead = *slot;
-+
-+            if (dead->value->ref_count > 0) {
-+                switch(dead->value->type) {
-+                    case APC_CACHE_ENTRY_FILE:
-+                        apc_log(APC_WARNING, "GC cache entry '%s' (dev=%d ino=%d) "
-+                            "was on gc-list for %d seconds", dead->value->data.file.filename,
-+                            dead->key.data.file.device, dead->key.data.file.inode, gc_sec);
-+                        break;
-+                    case APC_CACHE_ENTRY_USER:
-+                        apc_log(APC_WARNING, "GC cache entry '%s' "
-+                            "was on gc-list for %d seconds", dead->value->data.user.info, gc_sec);
-+                        break;
-+                }
-+            }
-+            *slot = dead->next;
-+            free_slot(dead);
-+        }
-+        else {
-+            slot = &(*slot)->next;
-+        }
++    if (p != NULL && (q = f(n)) != NULL) {
++        memcpy(q, p, n);
++        return q;
 +    }
++    return NULL;
 +}
++
 +/* }}} */
 +
-+/* {{{ prevent_garbage_collection */
-+static void prevent_garbage_collection(apc_cache_entry_t* entry)
++/* {{{ console display functions */
++
++static void my_log(int level, const char* fmt, va_list args)
 +{
-+    /* set reference counts on zend objects to an arbitrarily high value to
-+     * prevent garbage collection after execution */
++    static const char* level_strings[] = {
++        "apc-debug",
++        "apc-notice",
++        "apc-warning",
++        "apc-error"
++    };
++    static const int num_levels = NELEMS(level_strings);
 +
-+    enum { BIG_VALUE = 1000 };
++    time_t now;
++    char* buf;          /* for ctime */
 +
-+    if(entry->data.file.op_array) {
-+        entry->data.file.op_array->refcount[0] = BIG_VALUE;
++      TSRMLS_FETCH();
++
++    fflush(stdout);
++
++    if (level < 0)
++        level = 0;
++    else if (level >= num_levels)
++        level = num_levels-1;
++
++    now = time(0);
++    buf = ctime(&now);  /* TODO: replace with reentrant impl */
++    buf[24] = '\0';
++
++    fprintf(stderr, "[%s] [%s] ", buf, level_strings[level]);
++    vfprintf(stderr, fmt, args);
++
++    if (fmt[0] != '\0' && fmt[strlen(fmt)-1] == ':') {
++        fprintf(stderr, " %s", strerror(errno));
 +    }
-+    if (entry->data.file.functions) {
-+        int i;
-+        apc_function_t* fns = entry->data.file.functions;
-+        for (i=0; fns[i].function != NULL; i++) {
-+#ifdef ZEND_ENGINE_2            
-+            *(fns[i].function->op_array.refcount) = BIG_VALUE;
-+#else            
-+            fns[i].function->op_array.refcount[0] = BIG_VALUE;
-+#endif            
-+        }
++
++    if (zend_is_compiling(TSRMLS_C)) {
++        fprintf(stderr, " in %s on line %d.", zend_get_compiled_filename(TSRMLS_C), zend_get_compiled_lineno(TSRMLS_C)); 
++    } else if (zend_is_executing(TSRMLS_C)) {
++        fprintf(stderr, " in %s on line %d.", zend_get_executed_filename(TSRMLS_C), zend_get_executed_lineno(TSRMLS_C)); 
 +    }
-+    if (entry->data.file.classes) {
-+        int i;
-+        apc_class_t* classes = entry->data.file.classes;
-+        for (i=0; classes[i].class_entry != NULL; i++) {
-+#ifdef ZEND_ENGINE_2            
-+            classes[i].class_entry->refcount = BIG_VALUE;
-+#else            
-+            classes[i].class_entry->refcount[0] = BIG_VALUE;
-+#endif
-+        }
++    fprintf(stderr, "\n"); 
++
++    if (level == APC_ERROR) {
++        exit(2);
 +    }
 +}
-+/* }}} */
 +
-+/* {{{ apc_cache_create */
-+apc_cache_t* apc_cache_create(int size_hint, int gc_ttl, int ttl)
++void apc_eprint(const char* fmt, ...)
 +{
-+    apc_cache_t* cache;
-+    int cache_size;
-+    int num_slots;
-+    int i;
++    va_list args;
++    va_start(args, fmt);
++    my_log(APC_ERROR, fmt, args);
++    va_end(args);
++}
 +
-+    num_slots = size_hint > 0 ? size_hint*2 : 2000;
++void apc_wprint(const char* fmt, ...)
++{
++    va_list args;
++    va_start(args, fmt);
++    my_log(APC_WARNING, fmt, args);
++    va_end(args);
++}
 +
-+    cache = (apc_cache_t*) apc_emalloc(sizeof(apc_cache_t));
-+    cache_size = sizeof(header_t) + num_slots*sizeof(slot_t*);
++void apc_nprint(const char* fmt, ...)
++{
++    va_list args;
++    va_start(args, fmt);
++    my_log(APC_NOTICE, fmt, args);
++    va_end(args);
++}
 +
-+    cache->shmaddr = apc_sma_malloc(cache_size);
-+    if(!cache->shmaddr) {
-+        apc_eprint("Unable to allocate shared memory for cache structures.  (Perhaps your shared memory size isn't large enough?). ");
-+    }
-+    memset(cache->shmaddr, 0, cache_size);
++void apc_dprint(const char* fmt, ...)
++{
++#ifdef APC_DEBUG
++    va_list args;
++    va_start(args, fmt);
++    my_log(APC_DBG, fmt, args);
++    va_end(args);
++#endif
++}
 +
-+    cache->header = (header_t*) cache->shmaddr;
-+    cache->header->num_hits = 0;
-+    cache->header->num_misses = 0;
-+    cache->header->deleted_list = NULL;
-+    cache->header->start_time = time(NULL);
-+    cache->header->expunges = 0;
-+    cache->header->busy = 0;
++/* }}} */
 +
-+    cache->slots = (slot_t**) (((char*) cache->shmaddr) + sizeof(header_t));
-+    cache->num_slots = num_slots;
-+    cache->gc_ttl = gc_ttl;
-+    cache->ttl = ttl;
-+    CREATE_LOCK(cache->header->lock);
-+#if NONBLOCKING_LOCK_AVAILABLE
-+    CREATE_LOCK(cache->header->wrlock);
-+#endif
-+    for (i = 0; i < num_slots; i++) {
-+        cache->slots[i] = NULL;
-+    }
++/* {{{ string and text manipulation */
 +
-+    return cache;
++char* apc_append(const char* s, const char* t)
++{
++    int slen;
++    int tlen;
++    char* p;
++
++    slen = strlen(s);
++    tlen = strlen(t);
++
++    p = (char*) apc_emalloc((slen + tlen + 1) * sizeof(char));
++    memcpy(p, s, slen);
++    memcpy(p + slen, t, tlen + 1);
++
++    return p;
 +}
-+/* }}} */
 +
-+/* {{{ apc_cache_destroy */
-+void apc_cache_destroy(apc_cache_t* cache)
++char* apc_substr(const char* s, int start, int length)
 +{
-+    DESTROY_LOCK(cache);
-+    apc_efree(cache);
++    char* substr;
++    int src_len = strlen(s);
++
++    /* bring start into range */
++    if (start < 0) {
++        start = 0;
++    }
++    else if (start >= src_len) {
++        start = src_len - 1;
++    }
++
++    /* bring length into range */
++    if (length < 0 || src_len - start < length) {
++        length = src_len - start;
++    }
++
++    /* create the substring */
++    substr = apc_xmemcpy(s + start, length + 1, apc_emalloc);
++    substr[length] = '\0';
++    return substr;
 +}
-+/* }}} */
 +
-+/* {{{ apc_cache_clear */
-+void apc_cache_clear(apc_cache_t* cache)
++char** apc_tokenize(const char* s, char delim)
 +{
-+    int i;
++    char** tokens;      /* array of tokens, NULL terminated */
++    int size;           /* size of tokens array */
++    int n;              /* index of next token in tokens array */
++    int cur;            /* current position in input string */
++    int end;            /* final legal position in input string */
++    int next;           /* position of next delimiter in input */
 +
-+    if(!cache) return;
++    if (!s) {
++        return NULL;
++    }
 +
-+    LOCK(cache);
-+    cache->header->busy = 1;
-+    cache->header->num_hits = 0;
-+    cache->header->num_misses = 0;
-+    cache->header->start_time = time(NULL);
-+    cache->header->expunges = 0;
++    size = 2;
++    n    = 0;
++    cur  = 0;
++    end  = strlen(s) - 1;
 +
-+    for (i = 0; i < cache->num_slots; i++) {
-+        slot_t* p = cache->slots[i];
-+        while (p) {
-+            remove_slot(cache, &p);
++    tokens = (char**) apc_emalloc(size * sizeof(char*));
++    tokens[n] = NULL;
++
++    while (cur <= end) {
++        /* search for the next delimiter */
++        char* p = strchr(s + cur, delim);
++        next = p ? p-s : end+1;
++
++        /* resize token array if necessary */
++        if (n == size-1) {
++            size *= 2;
++            tokens = (char**) apc_erealloc(tokens, size * sizeof(char*));
 +        }
-+        cache->slots[i] = NULL;
++
++        /* save the current token */
++        tokens[n] = apc_substr(s, cur, next-cur);
++
++        tokens[++n] = NULL;
++        cur = next + 1;
 +    }
-+    
-+    cache->header->busy = 0;
-+    UNLOCK(cache);
++
++    return tokens;
 +}
++
 +/* }}} */
 +
-+/* {{{ apc_cache_expunge */
-+void apc_cache_expunge(apc_cache_t* cache, time_t t)
++/* {{{ apc stat */
++/* similar to php_stream_stat_path */
++#define APC_URL_STAT(wrapper, filename, pstatbuf) \
++    ((wrapper)->wops->url_stat((wrapper), (filename), PHP_STREAM_URL_STAT_QUIET, (pstatbuf), NULL TSRMLS_CC))
++int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo)
 +{
++    char** paths;
++    char *exec_fname;
++    int exec_fname_length;
++    int found = 0;
 +    int i;
++    php_stream_wrapper *wrapper = NULL;
++    char *path_for_open = NULL;
 +
-+    if(!cache) return;
++    TSRMLS_FETCH();
 +
-+    if(!cache->ttl) {
-+        /* 
-+         * If cache->ttl is not set, we wipe out the entire cache when
-+         * we run out of space. 
-+         */
-+        LOCK(cache);
-+        cache->header->busy = 1;
-+        cache->header->expunges++;
-+        for (i = 0; i < cache->num_slots; i++) {
-+            slot_t* p = cache->slots[i];
-+            while (p) {
-+                remove_slot(cache, &p);
-+            }
-+            cache->slots[i] = NULL;
-+        }
-+        cache->header->busy = 0;
-+        UNLOCK(cache);
-+    } else {
-+        slot_t **p;
++    assert(filename && fileinfo);
 +
-+        /*
-+         * If the ttl for the cache is set we walk through and delete stale 
-+         * entries.  For the user cache that is slightly confusing since
-+         * we have the individual entry ttl's we can look at, but that would be
-+         * too much work.  So if you want the user cache expunged, set a high
-+         * default apc.user_ttl and still provide a specific ttl for each entry
-+         * on insert
-+         */
 +
-+        LOCK(cache);
-+        cache->header->busy = 1;
-+        cache->header->expunges++;
-+        for (i = 0; i < cache->num_slots; i++) {
-+            p = &cache->slots[i];
-+            while(*p) {
-+                /* 
-+                 * For the user cache we look at the individual entry ttl values
-+                 * and if not set fall back to the default ttl for the user cache
-+                 */
-+                if((*p)->value->type == APC_CACHE_ENTRY_USER) {
-+                    if((*p)->value->data.user.ttl) {
-+                        if((*p)->creation_time + (*p)->value->data.user.ttl < t) {
-+                            remove_slot(cache, p);
-+                            continue;
-+                        }
-+                    } else if(cache->ttl) {
-+                        if((*p)->creation_time + cache->ttl < t) {
-+                            remove_slot(cache, p);
-+                            continue;
-+                        }
-+                    }
-+                } else if((*p)->access_time < (t - cache->ttl)) {
-+                    remove_slot(cache, p);
-+                    continue;
-+                }
-+                p = &(*p)->next;
-+            }
-+        }
-+        cache->header->busy = 0;
-+        UNLOCK(cache);
++    wrapper = php_stream_locate_url_wrapper(filename, &path_for_open, 0 TSRMLS_CC);
++
++    if(!wrapper || !wrapper->wops || !wrapper->wops->url_stat) {
++        return -1;
 +    }
-+}
-+/* }}} */
 +
-+/* {{{ apc_cache_insert */
-+int apc_cache_insert(apc_cache_t* cache,
-+                     apc_cache_key_t key,
-+                     apc_cache_entry_t* value,
-+                     time_t t)
-+{
-+    slot_t** slot;
++    if(wrapper != &php_plain_files_wrapper) {
++        if(APC_URL_STAT(wrapper, path_for_open, &fileinfo->st_buf) == 0) {
++            strncpy(fileinfo->fullpath, path_for_open, MAXPATHLEN);
++            return 0;
++        }
++        return -1; /* cannot stat */
++    }
 +
-+    if (!value) {
++    if (IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) && 
++            APC_URL_STAT(wrapper, path_for_open, &fileinfo->st_buf) == 0) {
++        strncpy(fileinfo->fullpath, path_for_open, MAXPATHLEN);
 +        return 0;
 +    }
 +
-+#ifdef __DEBUG_APC__
-+    fprintf(stderr,"Inserting [%s]\n", value->data.file.filename);
-+#endif
-+
-+    LOCK(cache);
-+    process_pending_removals(cache);
++    paths = apc_tokenize(path, DEFAULT_DIR_SEPARATOR);
++    if (!paths)
++        return -1;
 +
-+    if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
-+    else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
++    /* for each directory in paths, look for filename inside */
++    for (i = 0; paths[i]; i++) {
++        snprintf(fileinfo->fullpath, sizeof(fileinfo->fullpath), "%s%c%s", paths[i], DEFAULT_SLASH, path_for_open);
++        if (APC_URL_STAT(wrapper, fileinfo->fullpath, &fileinfo->st_buf) == 0) {
++            found = 1;
++            break;
++        }
++    }
 +
-+    while(*slot) {
-+      if(key.type == (*slot)->key.type) {
-+        if(key.type == APC_CACHE_KEY_FILE) {
-+            if(key_equals((*slot)->key.data.file, key.data.file)) {
-+                /* If existing slot for the same device+inode is different, remove it and insert the new version */
-+                if ((*slot)->key.mtime != key.mtime) {
-+                    remove_slot(cache, slot);
-+                    break;
-+                }
-+                UNLOCK(cache);
-+                return 0;
-+            } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
-+                remove_slot(cache, slot);
-+                continue;
-+            }
-+        } else {   /* APC_CACHE_KEY_FPFILE */
-+                if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
-+                /* Hrm.. it's already here, remove it and insert new one */
-+                remove_slot(cache, slot);
-+                break;
-+            } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
-+                remove_slot(cache, slot);
-+                continue;
++    /* check in path of the calling scripts' current working directory */
++    /* modified from main/streams/plain_wrapper.c */
++    if(!found && zend_is_executing(TSRMLS_C)) {
++        exec_fname = zend_get_executed_filename(TSRMLS_C);
++        exec_fname_length = strlen(exec_fname);
++        while((--exec_fname_length >= 0) && !IS_SLASH(exec_fname[exec_fname_length]));
++        if((exec_fname && exec_fname[0] != '[') && exec_fname_length > 0) {
++            /* not: [no active file] or no path */
++            memcpy(fileinfo->fullpath, exec_fname, exec_fname_length);
++            fileinfo->fullpath[exec_fname_length] = DEFAULT_SLASH;
++            strlcpy(fileinfo->fullpath +exec_fname_length +1, path_for_open,sizeof(fileinfo->fullpath)-exec_fname_length-1);
++            /* apc_wprint("filename: %s, exec_fname: %s, fileinfo->fullpath: %s", path_for_open, exec_fname, fileinfo->fullpath); */
++            if (APC_URL_STAT(wrapper, fileinfo->fullpath, &fileinfo->st_buf) == 0) {
++                found = 1;
 +            }
 +        }
-+      }
-+      slot = &(*slot)->next;
 +    }
 +
-+    if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
-+        UNLOCK(cache);
-+        return -1;
++    /* free the value returned by apc_tokenize */
++    for (i = 0; paths[i]; i++) {
++        apc_efree(paths[i]);
 +    }
-+   
-+    cache->header->mem_size += value->mem_size;
-+    cache->header->num_entries++;
-+    cache->header->num_inserts++;
-+    
-+    UNLOCK(cache);
-+    return 1;
++    apc_efree(paths);
++
++    return found ? 0 : -1;
 +}
++
 +/* }}} */
 +
-+/* {{{ apc_cache_user_insert */
-+int apc_cache_user_insert(apc_cache_t* cache, apc_cache_key_t key, apc_cache_entry_t* value, time_t t, int exclusive TSRMLS_DC)
-+{
-+    slot_t** slot;
-+    size_t* mem_size_ptr = NULL;
++/* {{{ regular expression wrapper functions */
 +
-+    if (!value) {
-+        return 0;
-+    }
++#if (HAVE_PCRE || HAVE_BUNDLED_PCRE)
++typedef struct {
++    pcre *preg;
++    pcre *nreg;
++} apc_regex;
 +
-+    LOCK(cache);
-+    process_pending_removals(cache);
++#define APC_ADD_PATTERN(match, pat) do {\
++    if(match.len > 1) {\
++        smart_str_appendc(&match, '|');\
++    }\
++    smart_str_appendc(&match, '(');\
++    while(*pat) {\
++        if(*pat == '/') smart_str_appendc(&match, '\\');\
++        \
++        smart_str_appendc(&match, *(pat++));\
++    }\
++    smart_str_appendc(&match, ')');\
++} while(0)
++
++#define APC_COMPILE_PATTERN(re, match) do {\
++    if(match.len > 2) { /* more than just "//" */\
++        if (((re) = pcre_get_compiled_regex(match.c, NULL, NULL TSRMLS_CC)) == NULL) {\
++            apc_wprint("apc_regex_compile_array: invalid expression '%s'", match.c); \
++            smart_str_free(&match);\
++            return NULL;\
++        }\
++    } else { \
++        (re) = NULL;\
++    }\
++} while(0)
++
++void* apc_regex_compile_array(char* patterns[] TSRMLS_DC)
++{
++    apc_regex* regs;
++    int npat;
++    smart_str pmatch = {0,};
++    smart_str nmatch = {0,};
++    char* pattern;
 +
-+    slot = &cache->slots[string_nhash_8(key.data.user.identifier, key.data.user.identifier_len) % cache->num_slots];
++    if (!patterns)
++        return NULL;
 +
-+    if (APCG(mem_size_ptr) != NULL) {
-+        mem_size_ptr = APCG(mem_size_ptr);
-+        APCG(mem_size_ptr) = NULL;
-+    }
++    regs = (apc_regex*) apc_emalloc(sizeof(apc_regex));
 +
-+    while (*slot) {
-+        if (!memcmp((*slot)->key.data.user.identifier, key.data.user.identifier, key.data.user.identifier_len)) {
-+            /* 
-+             * At this point we have found the user cache entry.  If we are doing 
-+             * an exclusive insert (apc_add) we are going to bail right away if
-+             * the user entry already exists and it has no ttl, or
-+             * there is a ttl and the entry has not timed out yet.
-+             */
-+            if(exclusive && (  !(*slot)->value->data.user.ttl ||
-+                              ( (*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) >= t ) 
-+                            ) ) {
-+                UNLOCK(cache);
-+                return 0;
-+            }
-+            remove_slot(cache, slot);
-+            break;
-+        } else 
-+        /* 
-+         * This is a bit nasty.  The idea here is to do runtime cleanup of the linked list of
-+         * slot entries so we don't always have to skip past a bunch of stale entries.  We check
-+         * for staleness here and get rid of them by first checking to see if the cache has a global
-+         * access ttl on it and removing entries that haven't been accessed for ttl seconds and secondly
-+         * we see if the entry has a hard ttl on it and remove it if it has been around longer than its ttl
-+         */
-+        if((cache->ttl && (*slot)->access_time < (t - cache->ttl)) || 
-+           ((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t)) {
-+            remove_slot(cache, slot);
-+            continue;
++    smart_str_appendc(&pmatch, '/');
++    smart_str_appendc(&nmatch, '/');
++
++    for (npat = 0; patterns[npat] != NULL; npat++) {
++        pattern = patterns[npat];
++        if(pattern[0] == '+') {
++            pattern += sizeof(char);
++            APC_ADD_PATTERN(pmatch, pattern);
++        } else {
++            if(pattern[0] == '-') pattern += sizeof(char);
++            APC_ADD_PATTERN(nmatch, pattern);
 +        }
-+        slot = &(*slot)->next;
 +    }
++    smart_str_appendc(&pmatch, '/');
++    smart_str_appendc(&nmatch, '/');
 +
-+    if (mem_size_ptr != NULL) {
-+        APCG(mem_size_ptr) = mem_size_ptr;
-+    }
++    smart_str_0(&nmatch);
++    smart_str_0(&pmatch);
 +
-+    if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
-+        UNLOCK(cache);
-+        return 0;
-+    }
-+    if (APCG(mem_size_ptr) != NULL) {
-+        value->mem_size = *APCG(mem_size_ptr);
-+        cache->header->mem_size += *APCG(mem_size_ptr);
-+    }
-+    cache->header->num_entries++;
-+    cache->header->num_inserts++;
++    APC_COMPILE_PATTERN(regs->preg, pmatch);
++    APC_COMPILE_PATTERN(regs->nreg, nmatch);
 +
-+    UNLOCK(cache);
-+    return 1;
++    smart_str_free(&pmatch);
++    smart_str_free(&nmatch);
++
++    return (void*) regs;
 +}
-+/* }}} */
 +
-+/* {{{ apc_cache_find_slot */
-+slot_t* apc_cache_find_slot(apc_cache_t* cache, apc_cache_key_t key, time_t t)
++void apc_regex_destroy_array(void* p)
 +{
-+    slot_t** slot;
-+    volatile slot_t* retval = NULL;
-+
-+    LOCK(cache);
-+    if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
-+    else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
-+
-+    while (*slot) {
-+      if(key.type == (*slot)->key.type) {
-+        if(key.type == APC_CACHE_KEY_FILE) {
-+            if(key_equals((*slot)->key.data.file, key.data.file)) {
-+                if((*slot)->key.mtime != key.mtime) {
-+                    remove_slot(cache, slot);
-+                    cache->header->num_misses++;
-+                    UNLOCK(cache);
-+                    return NULL;
-+                }
-+                (*slot)->num_hits++;
-+                (*slot)->value->ref_count++;
-+                (*slot)->access_time = t;
-+                prevent_garbage_collection((*slot)->value);
-+                cache->header->num_hits++;
-+                retval = *slot;
-+                UNLOCK(cache);
-+                return (slot_t*)retval;
-+            }
-+        } else {  /* APC_CACHE_KEY_FPFILE */
-+            if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
-+                /* TTL Check ? */
-+                (*slot)->num_hits++;
-+                (*slot)->value->ref_count++;
-+                (*slot)->access_time = t;
-+                prevent_garbage_collection((*slot)->value);
-+                cache->header->num_hits++;
-+                retval = *slot;
-+                UNLOCK(cache);
-+                return (slot_t*)retval;
-+            }
-+        }
-+      }
-+      slot = &(*slot)->next;
++    if (p != NULL) {
++        apc_regex* regs = (apc_regex*) p;
++        apc_efree(regs);
 +    }
-+    cache->header->num_misses++;
-+    UNLOCK(cache);
-+    return NULL;
 +}
-+/* }}} */
 +
-+/* {{{ apc_cache_find */
-+apc_cache_entry_t* apc_cache_find(apc_cache_t* cache, apc_cache_key_t key, time_t t)
-+{
-+    slot_t * slot = apc_cache_find_slot(cache, key, t);
-+    return (slot) ? slot->value : NULL;
-+}
-+/* }}} */
++#define APC_MATCH_PATTERN(re, input, output) do {\
++    if (re && pcre_exec(re, NULL, (input), strlen(input), 0, 0, NULL, 0) >= 0) {\
++        return (output);\
++    }\
++} while(0)
 +
-+/* {{{ apc_cache_user_find */
-+apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, int keylen, time_t t)
++
++int apc_regex_match_array(void* p, const char* input)
 +{
-+    slot_t** slot;
-+    volatile apc_cache_entry_t* value = NULL;
++    apc_regex* regs;
 +
-+    LOCK(cache);
++    if (!p)
++        return 0;
 +
-+    slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
++    regs = (apc_regex*) p;
 +
-+    while (*slot) {
-+        if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
-+            /* Check to make sure this entry isn't expired by a hard TTL */
-+            if((*slot)->value->data.user.ttl && ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) {
-+                remove_slot(cache, slot);
-+                UNLOCK(cache);
-+                return NULL;
-+            }
-+            /* Otherwise we are fine, increase counters and return the cache entry */
-+            (*slot)->num_hits++;
-+            (*slot)->value->ref_count++;
-+            (*slot)->access_time = t;
++    APC_MATCH_PATTERN(regs->preg, input, APC_POSITIVE_MATCH);
++    APC_MATCH_PATTERN(regs->nreg, input, APC_NEGATIVE_MATCH);
 +
-+            cache->header->num_hits++;
-+            value = (*slot)->value;
-+            UNLOCK(cache);
-+            return (apc_cache_entry_t*)value;
-+        }
-+        slot = &(*slot)->next;
++    return 0;
++}
++#else /* no pcre */
++void* apc_regex_compile_array(char* patterns[] TSRMLS_DC)
++{
++    if(patterns && patterns[0] != NULL) {
++        apc_wprint("pcre missing, disabling filters");
 +    }
-+ 
-+    UNLOCK(cache);
 +    return NULL;
 +}
++void apc_regex_destroy_array(void* p)
++{
++    /* nothing */
++}
++int apc_regex_match_array(void* p, const char* input)
++{
++    return 0;
++}
++#endif
 +/* }}} */
 +
-+/* {{{ apc_cache_user_delete */
-+int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen)
-+{
-+    slot_t** slot;
++/* {{{ crc32 implementation */
 +
-+    LOCK(cache);
++/* this table was generated by crc32gen() */
++static unsigned int crc32tab[] = {
++    /*   0 */  0x00000000, 0x3b83984b, 0x77073096, 0x4c84a8dd,
++    /*   4 */  0xee0e612c, 0xd58df967, 0x990951ba, 0xa28ac9f1,
++    /*   8 */  0x076dc419, 0x3cee5c52, 0x706af48f, 0x4be96cc4,
++    /*  12 */  0xe963a535, 0xd2e03d7e, 0x9e6495a3, 0xa5e70de8,
++    /*  16 */  0x0edb8832, 0x35581079, 0x79dcb8a4, 0x425f20ef,
++    /*  20 */  0xe0d5e91e, 0xdb567155, 0x97d2d988, 0xac5141c3,
++    /*  24 */  0x09b64c2b, 0x3235d460, 0x7eb17cbd, 0x4532e4f6,
++    /*  28 */  0xe7b82d07, 0xdc3bb54c, 0x90bf1d91, 0xab3c85da,
++    /*  32 */  0x1db71064, 0x2634882f, 0x6ab020f2, 0x5133b8b9,
++    /*  36 */  0xf3b97148, 0xc83ae903, 0x84be41de, 0xbf3dd995,
++    /*  40 */  0x1adad47d, 0x21594c36, 0x6ddde4eb, 0x565e7ca0,
++    /*  44 */  0xf4d4b551, 0xcf572d1a, 0x83d385c7, 0xb8501d8c,
++    /*  48 */  0x136c9856, 0x28ef001d, 0x646ba8c0, 0x5fe8308b,
++    /*  52 */  0xfd62f97a, 0xc6e16131, 0x8a65c9ec, 0xb1e651a7,
++    /*  56 */  0x14015c4f, 0x2f82c404, 0x63066cd9, 0x5885f492,
++    /*  60 */  0xfa0f3d63, 0xc18ca528, 0x8d080df5, 0xb68b95be,
++    /*  64 */  0x3b6e20c8, 0x00edb883, 0x4c69105e, 0x77ea8815,
++    /*  68 */  0xd56041e4, 0xeee3d9af, 0xa2677172, 0x99e4e939,
++    /*  72 */  0x3c03e4d1, 0x07807c9a, 0x4b04d447, 0x70874c0c,
++    /*  76 */  0xd20d85fd, 0xe98e1db6, 0xa50ab56b, 0x9e892d20,
++    /*  80 */  0x35b5a8fa, 0x0e3630b1, 0x42b2986c, 0x79310027,
++    /*  84 */  0xdbbbc9d6, 0xe038519d, 0xacbcf940, 0x973f610b,
++    /*  88 */  0x32d86ce3, 0x095bf4a8, 0x45df5c75, 0x7e5cc43e,
++    /*  92 */  0xdcd60dcf, 0xe7559584, 0xabd13d59, 0x9052a512,
++    /*  96 */  0x26d930ac, 0x1d5aa8e7, 0x51de003a, 0x6a5d9871,
++    /* 100 */  0xc8d75180, 0xf354c9cb, 0xbfd06116, 0x8453f95d,
++    /* 104 */  0x21b4f4b5, 0x1a376cfe, 0x56b3c423, 0x6d305c68,
++    /* 108 */  0xcfba9599, 0xf4390dd2, 0xb8bda50f, 0x833e3d44,
++    /* 112 */  0x2802b89e, 0x138120d5, 0x5f058808, 0x64861043,
++    /* 116 */  0xc60cd9b2, 0xfd8f41f9, 0xb10be924, 0x8a88716f,
++    /* 120 */  0x2f6f7c87, 0x14ece4cc, 0x58684c11, 0x63ebd45a,
++    /* 124 */  0xc1611dab, 0xfae285e0, 0xb6662d3d, 0x8de5b576,
++    /* 128 */  0x76dc4190, 0x4d5fd9db, 0x01db7106, 0x3a58e94d,
++    /* 132 */  0x98d220bc, 0xa351b8f7, 0xefd5102a, 0xd4568861,
++    /* 136 */  0x71b18589, 0x4a321dc2, 0x06b6b51f, 0x3d352d54,
++    /* 140 */  0x9fbfe4a5, 0xa43c7cee, 0xe8b8d433, 0xd33b4c78,
++    /* 144 */  0x7807c9a2, 0x438451e9, 0x0f00f934, 0x3483617f,
++    /* 148 */  0x9609a88e, 0xad8a30c5, 0xe10e9818, 0xda8d0053,
++    /* 152 */  0x7f6a0dbb, 0x44e995f0, 0x086d3d2d, 0x33eea566,
++    /* 156 */  0x91646c97, 0xaae7f4dc, 0xe6635c01, 0xdde0c44a,
++    /* 160 */  0x6b6b51f4, 0x50e8c9bf, 0x1c6c6162, 0x27eff929,
++    /* 164 */  0x856530d8, 0xbee6a893, 0xf262004e, 0xc9e19805,
++    /* 168 */  0x6c0695ed, 0x57850da6, 0x1b01a57b, 0x20823d30,
++    /* 172 */  0x8208f4c1, 0xb98b6c8a, 0xf50fc457, 0xce8c5c1c,
++    /* 176 */  0x65b0d9c6, 0x5e33418d, 0x12b7e950, 0x2934711b,
++    /* 180 */  0x8bbeb8ea, 0xb03d20a1, 0xfcb9887c, 0xc73a1037,
++    /* 184 */  0x62dd1ddf, 0x595e8594, 0x15da2d49, 0x2e59b502,
++    /* 188 */  0x8cd37cf3, 0xb750e4b8, 0xfbd44c65, 0xc057d42e,
++    /* 192 */  0x4db26158, 0x7631f913, 0x3ab551ce, 0x0136c985,
++    /* 196 */  0xa3bc0074, 0x983f983f, 0xd4bb30e2, 0xef38a8a9,
++    /* 200 */  0x4adfa541, 0x715c3d0a, 0x3dd895d7, 0x065b0d9c,
++    /* 204 */  0xa4d1c46d, 0x9f525c26, 0xd3d6f4fb, 0xe8556cb0,
++    /* 208 */  0x4369e96a, 0x78ea7121, 0x346ed9fc, 0x0fed41b7,
++    /* 212 */  0xad678846, 0x96e4100d, 0xda60b8d0, 0xe1e3209b,
++    /* 216 */  0x44042d73, 0x7f87b538, 0x33031de5, 0x088085ae,
++    /* 220 */  0xaa0a4c5f, 0x9189d414, 0xdd0d7cc9, 0xe68ee482,
++    /* 224 */  0x5005713c, 0x6b86e977, 0x270241aa, 0x1c81d9e1,
++    /* 228 */  0xbe0b1010, 0x8588885b, 0xc90c2086, 0xf28fb8cd,
++    /* 232 */  0x5768b525, 0x6ceb2d6e, 0x206f85b3, 0x1bec1df8,
++    /* 236 */  0xb966d409, 0x82e54c42, 0xce61e49f, 0xf5e27cd4,
++    /* 240 */  0x5edef90e, 0x655d6145, 0x29d9c998, 0x125a51d3,
++    /* 244 */  0xb0d09822, 0x8b530069, 0xc7d7a8b4, 0xfc5430ff,
++    /* 248 */  0x59b33d17, 0x6230a55c, 0x2eb40d81, 0x153795ca,
++    /* 252 */  0xb7bd5c3b, 0x8c3ec470, 0xc0ba6cad, 0xfb39f4e6,
++};
 +
-+    slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
++unsigned int apc_crc32(const char* buf, int len)
++{
++    int i;
++    int k;
++    unsigned int crc;
 +
-+    while (*slot) {
-+        if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
-+            remove_slot(cache, slot);
-+            UNLOCK(cache);
-+            return 1;
-+        }
-+        slot = &(*slot)->next;
++    /* preconditioning */
++    crc = 0xFFFFFFFF;
++
++    for (i = 0; i < len; i++) {
++        k = (crc ^ buf[i]) & 0x000000FF;
++        crc = ((crc >> 8) & 0x00FFFFFF) ^ crc32tab[k];
 +    }
 +
-+    UNLOCK(cache);
-+    return 0;
++    /* postconditioning */
++    return ~crc;
 +}
-+/* }}} */
 +
-+/* {{{ apc_cache_release */
-+void apc_cache_release(apc_cache_t* cache, apc_cache_entry_t* entry)
++/* crc32gen: generate the nth (0..255) crc32 table value */
++#if 0
++static unsigned long crc32gen(int n)
 +{
-+    /* local cache refcount-- is done in apc_local_cache_cleanup */
-+    if(entry->local) return;
++    int i;
++    unsigned long crc;
 +
-+    LOCK(cache);
-+    entry->ref_count--;
-+    UNLOCK(cache);
++    crc = n;
++    for (i = 8; i >= 0; i--) {
++        if (crc & 1) {
++            crc = (crc >> 1) ^ 0xEDB88320;
++        }
++        else {
++            crc >>= 1;
++        }
++    }
++    return crc;
 +}
-+/* }}} */
-+
-+/* {{{ apc_cache_make_file_key */
-+int apc_cache_make_file_key(apc_cache_key_t* key,
-+                       const char* filename,
-+                       const char* include_path,
-+                       time_t t
-+                                         TSRMLS_DC)
-+{
-+    struct stat *tmp_buf=NULL;
-+    struct apc_fileinfo_t fileinfo = { {0}, };
-+    int len;
-+
-+    assert(key != NULL);
-+
-+    if (!filename || !SG(request_info).path_translated) {
-+#ifdef __DEBUG_APC__
-+        fprintf(stderr,"No filename and no path_translated - bailing\n");
 +#endif
-+        return 0;
-+      }
 +
-+    len = strlen(filename);
-+    if(APCG(fpstat)==0) {
-+        if(IS_ABSOLUTE_PATH(filename,len)) {
-+            key->data.fpfile.fullpath = filename;
-+            key->data.fpfile.fullpath_len = len;
-+            key->mtime = t;
-+            key->type = APC_CACHE_KEY_FPFILE;
-+        } else {
-+            if (apc_search_paths(filename, include_path, &fileinfo) != 0) {
-+                apc_wprint("apc failed to locate %s - bailing", filename);
-+                return 0;
-+            }
++/* }}} */
 +
-+            if(!realpath(fileinfo.fullpath, APCG(canon_path))) {
-+                apc_wprint("realpath failed to canonicalize %s - bailing", filename);
-+                return 0;
-+            }
 +
-+            key->data.fpfile.fullpath = APCG(canon_path);
-+            key->data.fpfile.fullpath_len = strlen(APCG(canon_path));
-+            key->mtime = t;
-+            key->type = APC_CACHE_KEY_FPFILE;
-+        }
-+        return 1;
-+    } 
++/* {{{ apc_flip_hash() */
++HashTable* apc_flip_hash(HashTable *hash) {
++    zval **entry, *data;
++    HashTable *new_hash;
++    HashPosition pos;
 +
-+    if(!strcmp(SG(request_info).path_translated, filename)) {
-+        tmp_buf = sapi_get_stat(TSRMLS_C);  /* Apache has already done this stat() for us */
-+    }
-+    if(tmp_buf) { 
-+              fileinfo.st_buf = *tmp_buf;
-+    } else {
-+        if (apc_search_paths(filename, include_path, &fileinfo) != 0) {
-+#ifdef __DEBUG_APC__
-+            fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated);
-+#endif
-+            return 0;
-+        }
-+    }
++    if(hash == NULL) return hash;
 +
-+    if(APCG(max_file_size) < fileinfo.st_buf.st_size) {
-+#ifdef __DEBUG_APC__
-+        fprintf(stderr,"File is too big %s (%d - %ld) - bailing\n",filename,t,fileinfo.st_buf.st_size);
-+#endif
-+        return 0;
-+    }
++    MAKE_STD_ZVAL(data);
++    ZVAL_LONG(data, 1);
++    
++    new_hash = emalloc(sizeof(HashTable));
++    zend_hash_init(new_hash, hash->nTableSize, NULL, ZVAL_PTR_DTOR, 0);
 +
-+    /*
-+     * This is a bit of a hack.
-+     *
-+     * Here I am checking to see if the file is at least 2 seconds old.  
-+     * The idea is that if the file is currently being written to then its
-+     * mtime is going to match or at most be 1 second off of the current
-+     * request time and we want to avoid caching files that have not been
-+     * completely written.  Of course, people should be using atomic 
-+     * mechanisms to push files onto live web servers, but adding this
-+     * tiny safety is easier than educating the world.  This is now
-+     * configurable, but the default is still 2 seconds.
-+     */
-+    if(APCG(file_update_protection) && (t - fileinfo.st_buf.st_mtime < APCG(file_update_protection))) { 
-+#ifdef __DEBUG_APC__
-+        fprintf(stderr,"File is too new %s (%d - %d) - bailing\n",filename,t,fileinfo.st_buf.st_mtime);
-+#endif
-+        return 0;
++    zend_hash_internal_pointer_reset_ex(hash, &pos);
++    while (zend_hash_get_current_data_ex(hash, (void **)&entry, &pos) == SUCCESS) {
++        if(Z_TYPE_PP(entry) == IS_STRING) {
++            zend_hash_update(new_hash, Z_STRVAL_PP(entry), Z_STRLEN_PP(entry) +1, &data, sizeof(data), NULL);
++        } else {
++            zend_hash_index_update(new_hash, Z_LVAL_PP(entry), &data, sizeof(data), NULL);
++        }
++        Z_ADDREF_P(data);
++        zend_hash_move_forward_ex(hash, &pos);
 +    }
++    efree(data);
 +
-+    key->data.file.device = fileinfo.st_buf.st_dev;
-+    key->data.file.inode  = fileinfo.st_buf.st_ino;
-+    /* 
-+     * If working with content management systems that like to munge the mtime, 
-+     * it might be appropriate to key off of the ctime to be immune to systems
-+     * that try to backdate a template.  If the mtime is set to something older
-+     * than the previous mtime of a template we will obviously never see this
-+     * "older" template.  At some point the Smarty templating system did this.
-+     * I generally disagree with using the ctime here because you lose the 
-+     * ability to warm up new content by saving it to a temporary file, hitting
-+     * it once to cache it and then renaming it into its permanent location so
-+     * set the apc.stat_ctime=true to enable this check.
-+     */
-+    if(APCG(stat_ctime)) {
-+        key->mtime  = (fileinfo.st_buf.st_ctime > fileinfo.st_buf.st_mtime) ? fileinfo.st_buf.st_ctime : fileinfo.st_buf.st_mtime; 
-+    } else {
-+        key->mtime = fileinfo.st_buf.st_mtime;
-+    }
-+    key->type = APC_CACHE_KEY_FILE;
-+    return 1;
++    return new_hash;
 +}
 +/* }}} */
 +
-+/* {{{ apc_cache_make_user_key */
-+int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t)
-+{
-+    assert(key != NULL);
-+
-+    if (!identifier)
-+        return 0;
 +
-+    key->data.user.identifier = identifier;
-+    key->data.user.identifier_len = identifier_len;
-+    key->mtime = t;
-+    key->type = APC_CACHE_KEY_USER;
-+    return 1;
-+}
-+/* }}} */
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_cache.c php-5.3.1/ext/apc/apc_cache.c
+--- php-5.3.1.orig/ext/apc/apc_cache.c 1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_cache.c      1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,1183 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          Rasmus Lerdorf <rasmus@php.net>                             |
++  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
++  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
++  +----------------------------------------------------------------------+
 +
-+/* {{{ apc_cache_make_file_entry */
-+apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
-+                                        zend_op_array* op_array,
-+                                        apc_function_t* functions,
-+                                        apc_class_t* classes)
-+{
-+    apc_cache_entry_t* entry;
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
 +
-+    entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
-+    if (!entry) return NULL;
++   All other licensing and usage conditions are those of the PHP Group.
 +
-+    entry->data.file.filename  = apc_xstrdup(filename, apc_sma_malloc);
-+    if(!entry->data.file.filename) {
-+#ifdef __DEBUG_APC__
-+        fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is NULL - bailing\n");
-+#endif
-+        apc_sma_free(entry);
-+        return NULL;
-+    }
-+#ifdef __DEBUG_APC__
-+    fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is [%s]\n",entry->data.file.filename);
-+#endif
-+    entry->data.file.op_array  = op_array;
-+    entry->data.file.functions = functions;
-+    entry->data.file.classes   = classes;
-+    entry->type = APC_CACHE_ENTRY_FILE;
-+    entry->ref_count = 0;
-+    entry->mem_size = 0;
-+    entry->local = 0;
-+    return entry;
-+}
-+/* }}} */
++ */
 +
-+/* {{{ apc_cache_store_zval */
-+zval* apc_cache_store_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
-+{
-+    smart_str buf = {0};
-+    php_serialize_data_t var_hash;
-+    TSRMLS_FETCH();
++/* $Id: apc_cache.c 286717 2009-08-03 05:25:32Z gopalv $ */
 +
-+    if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
-+        if(!dst) {
-+            CHECK(dst = (zval*) allocate(sizeof(zval)));
-+        }
-+              
-+        PHP_VAR_SERIALIZE_INIT(var_hash);
-+        php_var_serialize(&buf, (zval**)&src, &var_hash TSRMLS_CC);
-+        PHP_VAR_SERIALIZE_DESTROY(var_hash);
-+              
-+        dst->type = IS_NULL; /* in case we fail */
-+        if(buf.c) {
-+            dst->type = src->type & ~IS_CONSTANT_INDEX;
-+            dst->value.str.len = buf.len;
-+            CHECK(dst->value.str.val = apc_xmemcpy(buf.c, buf.len+1, allocate));
-+            dst->type = src->type;
-+            smart_str_free(&buf);
-+        }
-+        return dst; 
-+    } else {
-+        
-+        /* Maintain a list of zvals we've copied to properly handle recursive structures */
-+        HashTable *old = APCG(copied_zvals);
-+        APCG(copied_zvals) = emalloc(sizeof(HashTable));
-+        zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
-+        
-+        dst = apc_copy_zval(dst, src, allocate, deallocate);
++#include "apc_cache.h"
++#include "apc_sma.h"
++#include "apc_main.h"
++#include "apc_globals.h"
++#include "SAPI.h"
 +
-+        if(APCG(copied_zvals)) {
-+            zend_hash_destroy(APCG(copied_zvals));
-+            efree(APCG(copied_zvals));
-+        }
++/* TODO: rehash when load factor exceeds threshold */
 +
-+        APCG(copied_zvals) = old;
++#define CHECK(p) { if ((p) == NULL) return NULL; }
 +
-+        return dst;
-+    }
-+}
++/* {{{ key_equals */
++#define key_equals(a, b) (a.inode==b.inode && a.device==b.device)
 +/* }}} */
 +
-+/* {{{ apc_cache_fetch_zval */
-+zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
-+{
-+    TSRMLS_FETCH();
-+    if((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
-+        php_unserialize_data_t var_hash;
-+        const unsigned char *p = (unsigned char*)Z_STRVAL_P(src);
-+
-+        PHP_VAR_UNSERIALIZE_INIT(var_hash);
-+        if(!php_var_unserialize(&dst, &p, p + Z_STRLEN_P(src), &var_hash TSRMLS_CC)) {
-+            PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
-+            zval_dtor(dst);
-+            php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - Z_STRVAL_P(src)), Z_STRLEN_P(src));
-+            dst->type = IS_NULL;
-+        }
-+        PHP_VAR_UNSERIALIZE_DESTROY(var_hash);                
-+        return dst; 
-+    } else {
-+    
-+        /* Maintain a list of zvals we've copied to properly handle recursive structures */
-+        HashTable *old = APCG(copied_zvals);
-+        APCG(copied_zvals) = emalloc(sizeof(HashTable));
-+        zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
-+        
-+        dst = apc_copy_zval(dst, src, allocate, deallocate);
-+
-+        if(APCG(copied_zvals)) {
-+            zend_hash_destroy(APCG(copied_zvals));
-+            efree(APCG(copied_zvals));
-+        }
-+
-+        APCG(copied_zvals) = old;
++static void apc_cache_expunge(apc_cache_t* cache, size_t size);
 +
-+        return dst;
-+    }
++/* {{{ hash */
++static unsigned int hash(apc_cache_key_t key)
++{
++    return key.data.file.device + key.data.file.inode;
 +}
 +/* }}} */
 +
-+/* {{{ apc_cache_free_zval */
-+void apc_cache_free_zval(zval* src, apc_free_t deallocate)
-+{
-+    TSRMLS_FETCH();
-+    if ((src->type & ~IS_CONSTANT_INDEX) == IS_OBJECT) {
-+        if (src->value.str.val) {
-+              deallocate(src->value.str.val);
-+        }
-+        deallocate(src);
-+    } else {
-+        /* Maintain a list of zvals we've copied to properly handle recursive structures */
-+        HashTable *old = APCG(copied_zvals);
-+        APCG(copied_zvals) = emalloc(sizeof(HashTable));
-+        zend_hash_init(APCG(copied_zvals), 0, NULL, NULL, 0);
-+        
-+        apc_free_zval(src, deallocate);
++/* {{{ string_nhash_8 */
++#define string_nhash_8(s,len) (unsigned int)(zend_inline_hash_func(s, len))
++/* }}} */
 +
-+        if(APCG(copied_zvals)) {
-+            zend_hash_destroy(APCG(copied_zvals));
-+            efree(APCG(copied_zvals));
-+        }
++/* {{{ make_slot */
++slot_t* make_slot(apc_cache_key_t key, apc_cache_entry_t* value, slot_t* next, time_t t)
++{
++    slot_t* p = apc_pool_alloc(value->pool, sizeof(slot_t));
 +
-+        APCG(copied_zvals) = old;
++    if (!p) return NULL;
++
++    if(value->type == APC_CACHE_ENTRY_USER) {
++        char *identifier = (char*) apc_pstrdup(key.data.user.identifier, value->pool);
++        if (!identifier) {
++            return NULL;
++        }
++        key.data.user.identifier = identifier;
++    } else if(key.type == APC_CACHE_KEY_FPFILE) {
++        char *fullpath = (char*) apc_pstrdup(key.data.fpfile.fullpath, value->pool);
++        if (!fullpath) {
++            return NULL;
++        }
++        key.data.fpfile.fullpath = fullpath;
 +    }
++    p->key = key;
++    p->value = value;
++    p->next = next;
++    p->num_hits = 0;
++    p->creation_time = t;
++    p->access_time = t;
++    p->deletion_time = 0;
++    return p;
 +}
 +/* }}} */
 +
-+/* {{{ apc_cache_make_user_entry */
-+apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval* val, const unsigned int ttl)
++/* {{{ free_slot */
++static void free_slot(slot_t* slot)
 +{
-+    apc_cache_entry_t* entry;
-+
-+    entry = (apc_cache_entry_t*) apc_sma_malloc(sizeof(apc_cache_entry_t));
-+    if (!entry) return NULL;
-+
-+    entry->data.user.info = apc_xmemcpy(info, info_len, apc_sma_malloc);
-+    entry->data.user.info_len = info_len;
-+    if(!entry->data.user.info) {
-+        apc_sma_free(entry);
-+        return NULL;
-+    }
-+    entry->data.user.val = apc_cache_store_zval(NULL, val, apc_sma_malloc, apc_sma_free);
-+    if(!entry->data.user.val) {
-+        apc_sma_free(entry->data.user.info);
-+        apc_sma_free(entry);
-+        return NULL;
-+    }
-+    INIT_PZVAL(entry->data.user.val);
-+    entry->data.user.ttl = ttl;
-+    entry->type = APC_CACHE_ENTRY_USER;
-+    entry->ref_count = 0;
-+    entry->mem_size = 0;
-+    entry->local = 0;
-+    return entry;
++    apc_pool_destroy(slot->value->pool);
 +}
 +/* }}} */
 +
-+/* {{{ apc_cache_free_entry */
-+void apc_cache_free_entry(apc_cache_entry_t* entry)
++/* {{{ remove_slot */
++static void remove_slot(apc_cache_t* cache, slot_t** slot)
 +{
-+    if (entry != NULL) {
-+        assert(entry->ref_count == 0);
-+        switch(entry->type) {
-+            case APC_CACHE_ENTRY_FILE:
-+                apc_sma_free(entry->data.file.filename);
-+                apc_free_op_array(entry->data.file.op_array, apc_sma_free);
-+                apc_free_functions(entry->data.file.functions, apc_sma_free);
-+                apc_free_classes(entry->data.file.classes, apc_sma_free);
-+                break;
-+            case APC_CACHE_ENTRY_USER:
-+                apc_sma_free(entry->data.user.info);
-+                apc_cache_free_zval(entry->data.user.val, apc_sma_free);
-+                break;
-+        }
-+        apc_sma_free(entry);
++    slot_t* dead = *slot;
++    *slot = (*slot)->next;
++
++    cache->header->mem_size -= dead->value->mem_size;
++    cache->header->num_entries--;
++    if (dead->value->ref_count <= 0) {
++        free_slot(dead);
++    }
++    else {
++        dead->next = cache->header->deleted_list;
++        dead->deletion_time = time(0);
++        cache->header->deleted_list = dead;
 +    }
 +}
 +/* }}} */
 +
-+/* {{{ apc_cache_info */
-+apc_cache_info_t* apc_cache_info(apc_cache_t* cache, zend_bool limited)
++/* {{{ process_pending_removals */
++static void process_pending_removals(apc_cache_t* cache)
 +{
-+    apc_cache_info_t* info;
-+    slot_t* p;
-+    int i;
-+
-+    if(!cache) return NULL;
++    slot_t** slot;
++    time_t now;
 +
-+    LOCK(cache);
++    /* This function scans the list of removed cache entries and deletes any
++     * entry whose reference count is zero (indicating that it is no longer
++     * being executed) or that has been on the pending list for more than
++     * cache->gc_ttl seconds (we issue a warning in the latter case).
++     */
 +
-+    info = (apc_cache_info_t*) apc_emalloc(sizeof(apc_cache_info_t));
-+    if(!info) {
-+        UNLOCK(cache);
-+        return NULL;
-+    }
-+    info->num_slots = cache->num_slots;
-+    info->ttl = cache->ttl;
-+    info->num_hits = cache->header->num_hits;
-+    info->num_misses = cache->header->num_misses;
-+    info->list = NULL;
-+    info->deleted_list = NULL;
-+    info->start_time = cache->header->start_time;
-+    info->expunges = cache->header->expunges;
-+    info->mem_size = cache->header->mem_size;
-+    info->num_entries = cache->header->num_entries;
-+    info->num_inserts = cache->header->num_inserts;
++    if (!cache->header->deleted_list)
++        return;
 +
-+    if(!limited) {
-+        /* For each hashtable slot */
-+        for (i = 0; i < info->num_slots; i++) {
-+            p = cache->slots[i];
-+            for (; p != NULL; p = p->next) {
-+                apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
++    slot = &cache->header->deleted_list;
++    now = time(0);
 +
-+                if(p->value->type == APC_CACHE_ENTRY_FILE) {
-+                    link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
-+                    link->data.file.device = p->key.data.file.device;
-+                    link->data.file.inode = p->key.data.file.inode;
-+                    link->type = APC_CACHE_ENTRY_FILE;
-+                } else if(p->value->type == APC_CACHE_ENTRY_USER) {
-+                    link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
-+                    link->data.user.ttl = p->value->data.user.ttl;
-+                    link->type = APC_CACHE_ENTRY_USER;
-+                }
-+                link->num_hits = p->num_hits;
-+                link->mtime = p->key.mtime;
-+                link->creation_time = p->creation_time;
-+                link->deletion_time = p->deletion_time;
-+                link->access_time = p->access_time;
-+                link->ref_count = p->value->ref_count;
-+                link->mem_size = p->value->mem_size;
-+                link->next = info->list;
-+                info->list = link;
-+            }
-+        }
++    while (*slot != NULL) {
++        int gc_sec = cache->gc_ttl ? (now - (*slot)->deletion_time) : 0;
 +
-+        /* For each slot pending deletion */
-+        for (p = cache->header->deleted_list; p != NULL; p = p->next) {
-+            apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
++        if ((*slot)->value->ref_count <= 0 || gc_sec > cache->gc_ttl) {
++            slot_t* dead = *slot;
 +
-+            if(p->value->type == APC_CACHE_ENTRY_FILE) {
-+                link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
-+                if(p->key.type == APC_CACHE_KEY_FILE) {
-+                    link->data.file.device = p->key.data.file.device;
-+                    link->data.file.inode = p->key.data.file.inode;
-+                } else { /* This is a no-stat fullpath file entry */
-+                    link->data.file.device = 0;
-+                    link->data.file.inode = 0;
++            if (dead->value->ref_count > 0) {
++                switch(dead->value->type) {
++                    case APC_CACHE_ENTRY_FILE:
++                        apc_wprint("GC cache entry '%s' (dev=%d ino=%d) was on gc-list for %d seconds", 
++                            dead->value->data.file.filename, dead->key.data.file.device, dead->key.data.file.inode, gc_sec);
++                        break;
++                    case APC_CACHE_ENTRY_USER:
++                        apc_wprint("GC cache entry '%s'was on gc-list for %d seconds", dead->value->data.user.info, gc_sec);
++                        break;
 +                }
-+                link->type = APC_CACHE_ENTRY_FILE;
-+            } else if(p->value->type == APC_CACHE_ENTRY_USER) {
-+                link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len, apc_emalloc);
-+                link->data.user.ttl = p->value->data.user.ttl;
-+                link->type = APC_CACHE_ENTRY_USER;
 +            }
-+            link->num_hits = p->num_hits;
-+            link->mtime = p->key.mtime;
-+            link->creation_time = p->creation_time;
-+            link->deletion_time = p->deletion_time;
-+            link->access_time = p->access_time;
-+            link->ref_count = p->value->ref_count;
-+            link->mem_size = p->value->mem_size;
-+            link->next = info->deleted_list;
-+            info->deleted_list = link;
++            *slot = dead->next;
++            free_slot(dead);
++        }
++        else {
++            slot = &(*slot)->next;
 +        }
 +    }
-+
-+    UNLOCK(cache);
-+    return info;
 +}
 +/* }}} */
 +
-+/* {{{ apc_cache_free_info */
-+void apc_cache_free_info(apc_cache_info_t* info)
++/* {{{ prevent_garbage_collection */
++static void prevent_garbage_collection(apc_cache_entry_t* entry)
 +{
-+    apc_cache_link_t* p = info->list;
-+    apc_cache_link_t* q = NULL;
-+    while (p != NULL) {
-+        q = p;
-+        p = p->next;
-+        if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
-+        else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
-+        apc_efree(q);
++    /* set reference counts on zend objects to an arbitrarily high value to
++     * prevent garbage collection after execution */
++
++    enum { BIG_VALUE = 1000 };
++
++    if(entry->data.file.op_array) {
++        entry->data.file.op_array->refcount[0] = BIG_VALUE;
 +    }
-+    p = info->deleted_list;
-+    while (p != NULL) {
-+        q = p;
-+        p = p->next;
-+        if(q->type == APC_CACHE_ENTRY_FILE) apc_efree(q->data.file.filename);
-+        else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
-+        apc_efree(q);
++    if (entry->data.file.functions) {
++        int i;
++        apc_function_t* fns = entry->data.file.functions;
++        for (i=0; fns[i].function != NULL; i++) {
++            *(fns[i].function->op_array.refcount) = BIG_VALUE;
++        }
++    }
++    if (entry->data.file.classes) {
++        int i;
++        apc_class_t* classes = entry->data.file.classes;
++        for (i=0; classes[i].class_entry != NULL; i++) {
++            classes[i].class_entry->refcount = BIG_VALUE;
++        }
 +    }
-+    apc_efree(info);
 +}
 +/* }}} */
 +
-+/* {{{ apc_cache_unlock */
-+void apc_cache_unlock(apc_cache_t* cache)
++/* {{{ apc_cache_create */
++apc_cache_t* apc_cache_create(int size_hint, int gc_ttl, int ttl)
 +{
-+    UNLOCK(cache);
-+}
-+/* }}} */
++    apc_cache_t* cache;
++    int cache_size;
++    int num_slots;
++    int i;
 +
-+/* {{{ apc_cache_busy */
-+zend_bool apc_cache_busy(apc_cache_t* cache)
-+{
-+    return cache->header->busy;
-+}
-+/* }}} */
++    num_slots = size_hint > 0 ? size_hint*2 : 2000;
++
++    cache = (apc_cache_t*) apc_emalloc(sizeof(apc_cache_t));
++    cache_size = sizeof(cache_header_t) + num_slots*sizeof(slot_t*);
++
++    cache->shmaddr = apc_sma_malloc(cache_size);
++    if(!cache->shmaddr) {
++        apc_eprint("Unable to allocate shared memory for cache structures.  (Perhaps your shared memory size isn't large enough?). ");
++    }
++    memset(cache->shmaddr, 0, cache_size);
++
++    cache->header = (cache_header_t*) cache->shmaddr;
++    cache->header->num_hits = 0;
++    cache->header->num_misses = 0;
++    cache->header->deleted_list = NULL;
++    cache->header->start_time = time(NULL);
++    cache->header->expunges = 0;
++    cache->header->busy = 0;
 +
++    cache->slots = (slot_t**) (((char*) cache->shmaddr) + sizeof(cache_header_t));
++    cache->num_slots = num_slots;
++    cache->gc_ttl = gc_ttl;
++    cache->ttl = ttl;
++    CREATE_LOCK(cache->header->lock);
 +#if NONBLOCKING_LOCK_AVAILABLE
-+/* {{{ apc_cache_write_lock */
-+zend_bool apc_cache_write_lock(apc_cache_t* cache)
-+{
-+    return apc_lck_nb_lock(cache->header->wrlock);
++    CREATE_LOCK(cache->header->wrlock);
++#endif
++    for (i = 0; i < num_slots; i++) {
++        cache->slots[i] = NULL;
++    }
++    cache->expunge_cb = apc_cache_expunge;
++    cache->has_lock = 0;
++
++    return cache;
 +}
 +/* }}} */
 +
-+/* {{{ apc_cache_write_unlock */
-+void apc_cache_write_unlock(apc_cache_t* cache)
++/* {{{ apc_cache_destroy */
++void apc_cache_destroy(apc_cache_t* cache)
 +{
-+    apc_lck_unlock(cache->header->wrlock);
++    DESTROY_LOCK(cache->header->lock);
++#ifdef NONBLOCKING_LOCK_AVAILABLE
++    DESTROY_LOCK(cache->header->wrlock);
++#endif
++    apc_efree(cache);
 +}
 +/* }}} */
-+#endif
 +
-+/* {{{ make_local_slot */
-+static local_slot_t* make_local_slot(apc_local_cache_t* cache, local_slot_t* lslot, slot_t* slot, time_t t) 
-+{
-+    apc_cache_entry_t* value;
++/* {{{ apc_cache_clear */
++void apc_cache_clear(apc_cache_t* cache)
++{
++    int i;
++
++    if(!cache) return;
++
++    CACHE_LOCK(cache);
++    cache->header->busy = 1;
++    cache->header->num_hits = 0;
++    cache->header->num_misses = 0;
++    cache->header->start_time = time(NULL);
++    cache->header->expunges = 0;
 +
-+    value = apc_emalloc(sizeof(apc_cache_entry_t));
-+    memcpy(value, slot->value, sizeof(apc_cache_entry_t)); /* bitwise copy */
-+    value->local = 1;
++    for (i = 0; i < cache->num_slots; i++) {
++        slot_t* p = cache->slots[i];
++        while (p) {
++            remove_slot(cache, &p);
++        }
++        cache->slots[i] = NULL;
++    }
 +
-+    lslot->original = slot;
-+    lslot->value = value;
-+    lslot->num_hits = 0;
-+    lslot->creation_time = t;
++    memset(&cache->header->lastkey, 0, sizeof(apc_keyid_t));
 +
-+    return lslot; /* for what joy ? ... consistency */
++    cache->header->busy = 0;
++    CACHE_UNLOCK(cache);
 +}
 +/* }}} */
 +
-+/* {{{ free_local_slot */
-+static void free_local_slot(apc_local_cache_t* cache, local_slot_t* lslot) 
++/* {{{ apc_cache_expunge */
++static void apc_cache_expunge(apc_cache_t* cache, size_t size)
 +{
-+    local_slot_t * dead = NULL;
-+    if(!lslot->original) return;
++    int i;
++    time_t t;
++    TSRMLS_FETCH();
 +
-+    /* TODO: Bad design to allocate memory in a free_* - fix when bored (hehe) */
-+    dead = apc_emalloc(sizeof(local_slot_t));
-+    memcpy(dead, lslot, sizeof(local_slot_t)); /* bitwise copy */
++    t = apc_time();
++
++    if(!cache) return;
++
++    if(!cache->ttl) {
++        /*
++         * If cache->ttl is not set, we wipe out the entire cache when
++         * we run out of space.
++         */
++        CACHE_SAFE_LOCK(cache);
++        cache->header->busy = 1;
++        cache->header->expunges++;
++        for (i = 0; i < cache->num_slots; i++) {
++            slot_t* p = cache->slots[i];
++            while (p) {
++                remove_slot(cache, &p);
++            }
++            cache->slots[i] = NULL;
++        }
++        cache->header->busy = 0;
++        CACHE_SAFE_UNLOCK(cache);
++    } else {
++        slot_t **p;
 +
-+    lslot->original = NULL;
-+    lslot->value = NULL;
++        /*
++         * If the ttl for the cache is set we walk through and delete stale 
++         * entries.  For the user cache that is slightly confusing since
++         * we have the individual entry ttl's we can look at, but that would be
++         * too much work.  So if you want the user cache expunged, set a high
++         * default apc.user_ttl and still provide a specific ttl for each entry
++         * on insert
++         */
 +
-+    dead->next = cache->dead_list;
-+    cache->dead_list = dead;
++        CACHE_SAFE_LOCK(cache);
++        cache->header->busy = 1;
++        cache->header->expunges++;
++        for (i = 0; i < cache->num_slots; i++) {
++            p = &cache->slots[i];
++            while(*p) {
++                /*
++                 * For the user cache we look at the individual entry ttl values
++                 * and if not set fall back to the default ttl for the user cache
++                 */
++                if((*p)->value->type == APC_CACHE_ENTRY_USER) {
++                    if((*p)->value->data.user.ttl) {
++                        if((time_t) ((*p)->creation_time + (*p)->value->data.user.ttl) < t) {
++                            remove_slot(cache, p);
++                            continue;
++                        }
++                    } else if(cache->ttl) {
++                        if((*p)->creation_time + cache->ttl < t) {
++                            remove_slot(cache, p);
++                            continue;
++                        }
++                    }
++                } else if((*p)->access_time < (t - cache->ttl)) {
++                    remove_slot(cache, p);
++                    continue;
++                }
++                p = &(*p)->next;
++            }
++        }
++        cache->header->busy = 0;
++        CACHE_SAFE_UNLOCK(cache);
++    }
 +}
 +/* }}} */
 +
-+/* {{{ apc_local_cache_create */
-+apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl)
++/* {{{ apc_cache_insert */
++static inline int _apc_cache_insert(apc_cache_t* cache,
++                     apc_cache_key_t key,
++                     apc_cache_entry_t* value,
++                     apc_context_t* ctxt,
++                     time_t t)
 +{
-+    apc_local_cache_t* cache = NULL;
++    slot_t** slot;
 +
-+    cache = (apc_local_cache_t*) apc_emalloc(sizeof(apc_local_cache_t));
++    if (!value) {
++        return 0;
++    }
 +
-+    cache->slots = (local_slot_t*) (apc_emalloc(sizeof(local_slot_t) * num_slots));
-+    memset(cache->slots, 0, sizeof(local_slot_t) * num_slots);
++#ifdef __DEBUG_APC__
++    fprintf(stderr,"Inserting [%s]\n", value->data.file.filename);
++#endif
 +
-+    cache->shmcache = shmcache;
-+    cache->num_slots = num_slots;
-+    cache->ttl = ttl;
-+    cache->num_hits = 0;
-+    cache->generation = shmcache->header->expunges;
-+    cache->dead_list = NULL;
++    process_pending_removals(cache);
 +
-+    return cache;
-+}
-+/* }}} */
++    if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
++    else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
 +
-+/* {{{ apc_local_cache_cleanup */
-+void apc_local_cache_cleanup(apc_local_cache_t* cache) {
-+    local_slot_t * lslot;
-+    time_t t = time(0);
-+    
-+    int i;
-+    for(i = 0; i < cache->num_slots; i++) {
-+        lslot = &cache->slots[i];
-+        /* every slot lives for exactly TTL seconds */
-+        if((lslot->original && lslot->creation_time < (t - cache->ttl)) ||
-+                cache->generation != cache->shmcache->header->expunges) {
-+            free_local_slot(cache, lslot);
++    while(*slot) {
++      if(key.type == (*slot)->key.type) {
++        if(key.type == APC_CACHE_KEY_FILE) {
++            if(key_equals((*slot)->key.data.file, key.data.file)) {
++                /* If existing slot for the same device+inode is different, remove it and insert the new version */
++                if (ctxt->force_update || (*slot)->key.mtime != key.mtime) {
++                    remove_slot(cache, slot);
++                    break;
++                }
++                return 0;
++            } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
++                remove_slot(cache, slot);
++                continue;
++            }
++        } else {   /* APC_CACHE_KEY_FPFILE */
++            if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
++                /* Hrm.. it's already here, remove it and insert new one */
++                remove_slot(cache, slot);
++                break;
++            } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
++                remove_slot(cache, slot);
++                continue;
++            }
 +        }
++      }
++      slot = &(*slot)->next;
 +    }
 +
-+    LOCK(cache->shmcache);
-+    for(lslot = cache->dead_list; lslot != NULL; lslot = lslot->next) {
-+        lslot->original->num_hits += lslot->num_hits;
-+        lslot->original->value->ref_count--; /* apc_cache_release(cache->shmcache, lslot->original->value); */
-+        apc_efree(lslot->value);
++    if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
++        return -1;
 +    }
-+    UNLOCK(cache->shmcache);
 +
-+    cache->dead_list = NULL;
++    value->mem_size = ctxt->pool->size;
++    cache->header->mem_size += ctxt->pool->size;
++    cache->header->num_entries++;
++    cache->header->num_inserts++;
++
++    return 1;
 +}
 +/* }}} */
 +
-+/* {{{ apc_local_cache_destroy */
-+void apc_local_cache_destroy(apc_local_cache_t* cache)
++/* {{{ apc_cache_insert */
++int apc_cache_insert(apc_cache_t* cache, apc_cache_key_t key, apc_cache_entry_t* value, apc_context_t *ctxt, time_t t)
 +{
-+    int i;
-+    for(i = 0; i < cache->num_slots; i++) {
-+        free_local_slot(cache, &cache->slots[i]);
-+    }
-+
-+    apc_local_cache_cleanup(cache);
-+
-+    LOCK(cache->shmcache);
-+    cache->shmcache->header->num_hits += cache->num_hits;
-+    UNLOCK(cache->shmcache);
-+
-+    apc_efree(cache->slots);
-+    apc_efree(cache);
++    int rval;
++    CACHE_LOCK(cache);
++    rval = _apc_cache_insert(cache, key, value, ctxt, t);
++    CACHE_UNLOCK(cache);
++    return rval;
 +}
 +/* }}} */
 +
-+/* {{{ apc_local_cache_find */
-+apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t)
++/* {{{ apc_cache_insert */
++int *apc_cache_insert_mult(apc_cache_t* cache, apc_cache_key_t* keys, apc_cache_entry_t** values, apc_context_t *ctxt, time_t t, int num_entries)
 +{
-+    slot_t* slot;
-+    local_slot_t* lslot; 
++    int *rval;
++    int i;
 +
-+    if(key.type == APC_CACHE_KEY_FILE) lslot = &cache->slots[hash(key) % cache->num_slots];
-+    else lslot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
++    rval = emalloc(sizeof(int) * num_entries);
++    CACHE_LOCK(cache);
++    for (i=0; i < num_entries; i++) {
++        if (values[i]) {
++            ctxt->pool = values[i]->pool;
++            rval[i] = _apc_cache_insert(cache, keys[i], values[i], ctxt, t);
++        }
++    }
++    CACHE_UNLOCK(cache);
++    return rval;
++}
++/* }}} */
 +
-+    slot = lslot->original;
 +
-+    if(slot && key.type == slot->key.type) {
-+        if(slot->access_time < (t - cache->ttl)) {
-+            goto not_found;
-+        }
-+        if(key.type == APC_CACHE_KEY_FILE && 
-+           key_equals(slot->key.data.file, key.data.file)) {
-+            if(slot->key.mtime != key.mtime) {
-+                free_local_slot(cache, lslot);
-+                goto not_found;
-+            }
-+            cache->num_hits++;
-+            lslot->num_hits++;
-+            lslot->original->access_time = t; /* unlocked write, but last write wins */
-+            return lslot->value;
-+        } else if(key.type == APC_CACHE_KEY_FPFILE) {
-+            if(!memcmp(slot->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
-+                cache->num_hits++;
-+                lslot->num_hits++;
-+                lslot->original->access_time = t; /* unlocked write, but last write wins */
-+                return lslot->value;
-+            }
-+        }
++/* {{{ apc_cache_user_insert */
++int apc_cache_user_insert(apc_cache_t* cache, apc_cache_key_t key, apc_cache_entry_t* value, apc_context_t* ctxt, time_t t, int exclusive TSRMLS_DC)
++{
++    slot_t** slot;
++    unsigned int keylen = key.data.user.identifier_len+1;
++    unsigned int h = string_nhash_8(key.data.user.identifier, keylen);
++    apc_keyid_t *lastkey = &cache->header->lastkey;
++    
++    if (!value) {
++        return 0;
 +    }
-+not_found:
-+    if(apc_cache_busy(cache->shmcache)) {
-+        return NULL;
++    
++    if(apc_cache_busy(cache)) {
++        /* cache cleanup in progress, do not wait */ 
++        return 0;
 +    }
 +
-+    slot = apc_cache_find_slot(cache->shmcache, key, t);
-+
-+    if(!slot) return NULL;
-+   
-+    /* i.e maintain a sort of top list */
-+    if(lslot->original == NULL || (lslot->original->num_hits + lslot->num_hits)  < slot->num_hits) {
-+        free_local_slot(cache, lslot);
-+        make_local_slot(cache, lslot, slot, t); 
-+        return lslot->value;
++    if(apc_cache_is_last_key(cache, &key, t)) {
++        /* potential cache slam */
++        return 0;
 +    }
-+    return slot->value;
-+}
-+/* }}} */
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_cache.h php-5.2.5/ext/apc/apc_cache.h
---- php-5.2.5-orig/ext/apc/apc_cache.h 1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_cache.h      2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,312 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt.                                 |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  +----------------------------------------------------------------------+
++    CACHE_LOCK(cache);
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++    memset(lastkey, 0, sizeof(apc_keyid_t));
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++    lastkey->h = h;
++    lastkey->keylen = keylen;
++    lastkey->mtime = t;
++    
++    /* we do not reset lastkey after the insert. Whether it is inserted 
++     * or not, another insert in the same second is always a bad idea. 
++     */
 +
-+ */
++    process_pending_removals(cache);
++    
++    slot = &cache->slots[h % cache->num_slots];
 +
-+/* $Id: apc_cache.h,v 3.46 2007/10/05 23:06:56 gopalv Exp $ */
++    while (*slot) {
++        if (!memcmp((*slot)->key.data.user.identifier, key.data.user.identifier, keylen)) {
++            /* 
++             * At this point we have found the user cache entry.  If we are doing 
++             * an exclusive insert (apc_add) we are going to bail right away if
++             * the user entry already exists and it has no ttl, or
++             * there is a ttl and the entry has not timed out yet.
++             */
++            if(exclusive && (  !(*slot)->value->data.user.ttl ||
++                              ( (*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) >= t ) 
++                            ) ) {
++                goto fail;
++            }
++            remove_slot(cache, slot);
++            break;
++        } else 
++        /* 
++         * This is a bit nasty.  The idea here is to do runtime cleanup of the linked list of
++         * slot entries so we don't always have to skip past a bunch of stale entries.  We check
++         * for staleness here and get rid of them by first checking to see if the cache has a global
++         * access ttl on it and removing entries that haven't been accessed for ttl seconds and secondly
++         * we see if the entry has a hard ttl on it and remove it if it has been around longer than its ttl
++         */
++        if((cache->ttl && (*slot)->access_time < (t - cache->ttl)) || 
++           ((*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t)) {
++            remove_slot(cache, slot);
++            continue;
++        }
++        slot = &(*slot)->next;
++    }
 +
-+#ifndef APC_CACHE_H
-+#define APC_CACHE_H
++    if ((*slot = make_slot(key, value, *slot, t)) == NULL) {
++        goto fail;
++    } 
++    
++    value->mem_size = ctxt->pool->size;
++    cache->header->mem_size += ctxt->pool->size;
 +
-+/*
-+ * This module defines the shared memory file cache. Basically all of the
-+ * logic for storing and retrieving cache entries lives here.
-+ */
++    cache->header->num_entries++;
++    cache->header->num_inserts++;
 +
-+#include "apc.h"
-+#include "apc_compile.h"
++    CACHE_UNLOCK(cache);
 +
-+#define APC_CACHE_ENTRY_FILE   1
-+#define APC_CACHE_ENTRY_USER   2
++    return 1;
 +
-+#define APC_CACHE_KEY_FILE     1
-+#define APC_CACHE_KEY_USER     2
-+#define APC_CACHE_KEY_FPFILE   3
++fail:
++    CACHE_UNLOCK(cache);
 +
-+/* {{{ struct definition: apc_cache_key_t */
-+#define T apc_cache_t*
-+typedef struct apc_cache_t apc_cache_t; /* opaque cache type */
++    return 0;
++}
++/* }}} */
 +
-+typedef union _apc_cache_key_data_t {
-+    struct {
-+        dev_t device;             /* the filesystem device */
-+        ino_t inode;              /* the filesystem inode */
-+    } file;
-+    struct {
-+        const char *identifier;
-+        int identifier_len;
-+    } user;
-+    struct {
-+        const char *fullpath;
-+        int fullpath_len;
-+    } fpfile;
-+} apc_cache_key_data_t;
-+
-+typedef struct apc_cache_key_t apc_cache_key_t;
-+struct apc_cache_key_t {
-+    apc_cache_key_data_t data;
-+    time_t mtime;                 /* the mtime of this cached entry */
-+    unsigned char type;
-+};
-+/* }}} */
++/* {{{ apc_cache_find_slot */
++slot_t* apc_cache_find_slot(apc_cache_t* cache, apc_cache_key_t key, time_t t)
++{
++    slot_t** slot;
++    volatile slot_t* retval = NULL;
 +
-+/* {{{ struct definition: apc_cache_entry_t */
-+typedef union _apc_cache_entry_value_t {
-+    struct {
-+        char *filename;             /* absolute path to source file */
-+        zend_op_array* op_array;    /* op_array allocated in shared memory */
-+        apc_function_t* functions;  /* array of apc_function_t's */
-+        apc_class_t* classes;       /* array of apc_class_t's */
-+    } file;
-+    struct {
-+        char *info; 
-+        int info_len; 
-+        zval *val;
-+        unsigned int ttl;
-+    } user;
-+} apc_cache_entry_value_t;
++    CACHE_LOCK(cache);
++    if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
++    else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
 +
-+typedef struct apc_cache_entry_t apc_cache_entry_t;
-+struct apc_cache_entry_t {
-+    apc_cache_entry_value_t data;
-+    unsigned char type;
-+    unsigned char local;
-+    int ref_count;
-+    size_t mem_size;
-+};
++    while (*slot) {
++      if(key.type == (*slot)->key.type) {
++        if(key.type == APC_CACHE_KEY_FILE) {
++            if(key_equals((*slot)->key.data.file, key.data.file)) {
++                if((*slot)->key.mtime != key.mtime) {
++                    remove_slot(cache, slot);
++                    cache->header->num_misses++;
++                    CACHE_UNLOCK(cache);
++                    return NULL;
++                }
++                (*slot)->num_hits++;
++                (*slot)->value->ref_count++;
++                (*slot)->access_time = t;
++                prevent_garbage_collection((*slot)->value);
++                cache->header->num_hits++;
++                retval = *slot;
++                CACHE_UNLOCK(cache);
++                return (slot_t*)retval;
++            }
++        } else {  /* APC_CACHE_KEY_FPFILE */
++            if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
++                /* TTL Check ? */
++                (*slot)->num_hits++;
++                (*slot)->value->ref_count++;
++                (*slot)->access_time = t;
++                prevent_garbage_collection((*slot)->value);
++                cache->header->num_hits++;
++                retval = *slot;
++                CACHE_UNLOCK(cache);
++                return (slot_t*)retval;
++            }
++        }
++      }
++      slot = &(*slot)->next;
++    }
++    cache->header->num_misses++;
++    CACHE_UNLOCK(cache);
++    return NULL;
++}
 +/* }}} */
 +
-+/*
-+ * apc_cache_create creates the shared memory compiler cache. This function
-+ * should be called just once (ideally in the web server parent process, e.g.
-+ * in apache), otherwise you will end up with multiple caches (which won't
-+ * necessarily break anything). Returns a pointer to the cache object.
-+ *
-+ * size_hint is a "hint" at the total number of source files that will be
-+ * cached. It determines the physical size of the hash table. Passing 0 for
-+ * this argument will use a reasonable default value.
-+ *
-+ * gc_ttl is the maximum time a cache entry may speed on the garbage
-+ * collection list. This is basically a work around for the inherent
-+ * unreliability of our reference counting mechanism (see apc_cache_release).
-+ *
-+ * ttl is the maximum time a cache entry can idle in a slot in case the slot
-+ * is needed.  This helps in cleaning up the cache and ensuring that entries 
-+ * hit frequently stay cached and ones not hit very often eventually disappear.
-+ */
-+extern T apc_cache_create(int size_hint, int gc_ttl, int ttl);
++/* {{{ apc_cache_find */
++apc_cache_entry_t* apc_cache_find(apc_cache_t* cache, apc_cache_key_t key, time_t t)
++{
++    slot_t * slot = apc_cache_find_slot(cache, key, t);
++    return (slot) ? slot->value : NULL;
++}
++/* }}} */
 +
-+/*
-+ * apc_cache_destroy releases any OS resources associated with a cache object.
-+ * Under apache, this function can be safely called by the child processes
-+ * when they exit.
-+ */
-+extern void apc_cache_destroy(T cache);
++/* {{{ apc_cache_user_find */
++apc_cache_entry_t* apc_cache_user_find(apc_cache_t* cache, char *strkey, int keylen, time_t t)
++{
++    slot_t** slot;
++    volatile apc_cache_entry_t* value = NULL;
 +
-+/*
-+ * apc_cache_clear empties a cache. This can safely be called at any time,
-+ * even while other server processes are executing cached source files.
-+ */
-+extern void apc_cache_clear(T cache);
++    if(apc_cache_busy(cache))
++    {
++        /* cache cleanup in progress */ 
++        return NULL;
++    }
 +
-+/*
-+ * apc_cache_insert adds an entry to the cache, using a filename as a key.
-+ * Internally, the filename is translated to a canonical representation, so
-+ * that relative and absolute filenames will map to a single key. Returns
-+ * non-zero if the file was successfully inserted, 0 otherwise. If 0 is
-+ * returned, the caller must free the cache entry by calling
-+ * apc_cache_free_entry (see below).
-+ *
-+ * key is the value created by apc_cache_make_file_key for file keys.
-+ *
-+ * value is a cache entry returned by apc_cache_make_entry (see below).
-+ */
-+extern int apc_cache_insert(T cache, apc_cache_key_t key,
-+                            apc_cache_entry_t* value, time_t t);
++    CACHE_LOCK(cache);
 +
-+extern int apc_cache_user_insert(T cache, apc_cache_key_t key,
-+                            apc_cache_entry_t* value, time_t t, int exclusive TSRMLS_DC);
++    slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
 +
-+/*
-+ * apc_cache_find searches for a cache entry by filename, and returns a
-+ * pointer to the entry if found, NULL otherwise.
-+ *
-+ * key is a value created by apc_cache_make_file_key for file keys.
-+ */
-+extern apc_cache_entry_t* apc_cache_find(T cache, apc_cache_key_t key, time_t t);
++    while (*slot) {
++        if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
++            /* Check to make sure this entry isn't expired by a hard TTL */
++            if((*slot)->value->data.user.ttl && (time_t) ((*slot)->creation_time + (*slot)->value->data.user.ttl) < t) {
++                remove_slot(cache, slot);
++                cache->header->num_misses++;
++                CACHE_UNLOCK(cache);
++                return NULL;
++            }
++            /* Otherwise we are fine, increase counters and return the cache entry */
++            (*slot)->num_hits++;
++            (*slot)->value->ref_count++;
++            (*slot)->access_time = t;
 +
-+/*
-+ * apc_cache_user_find searches for a cache entry by its hashed identifier, 
-+ * and returns a pointer to the entry if found, NULL otherwise.
-+ *
-+ */
-+extern apc_cache_entry_t* apc_cache_user_find(T cache, char* strkey, int keylen, time_t t);
++            cache->header->num_hits++;
++            value = (*slot)->value;
++            CACHE_UNLOCK(cache);
++            return (apc_cache_entry_t*)value;
++        }
++        slot = &(*slot)->next;
++    }
++ 
++    cache->header->num_misses++;
++    CACHE_UNLOCK(cache);
++    return NULL;
++}
++/* }}} */
 +
-+/*
-+ * apc_cache_user_delete finds an entry in the user cache and deletes it.
-+ */
-+extern int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen);
++/* {{{ apc_cache_user_update */
++int _apc_cache_user_update(apc_cache_t* cache, char *strkey, int keylen, apc_cache_updater_t updater, void* data TSRMLS_DC)
++{
++    slot_t** slot;
++    int retval;
 +
-+/* apc_cach_fetch_zval takes a zval in the cache and reconstructs a runtime
-+ * zval from it.
-+ *
-+ */
-+zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
++    if(apc_cache_busy(cache))
++    {
++        /* cache cleanup in progress */ 
++        return 0;
++    }
 +
-+/*
-+ * apc_cache_release decrements the reference count associated with a cache
-+ * entry. Calling apc_cache_find automatically increments the reference count,
-+ * and this function must be called post-execution to return the count to its
-+ * original value. Failing to do so will prevent the entry from being
-+ * garbage-collected.
-+ *
-+ * entry is the cache entry whose ref count you want to decrement.
-+ */
-+extern void apc_cache_release(T cache, apc_cache_entry_t* entry);
++    CACHE_LOCK(cache);
 +
-+/*
-+ * apc_cache_make_file_key creates a key object given a relative or absolute
-+ * filename and an optional list of auxillary paths to search. include_path is
-+ * searched if the filename cannot be found relative to the current working
-+ * directory.
-+ *
-+ * key points to caller-allocated storage (must not be null).
-+ *
-+ * filename is the path to the source file.
-+ *
-+ * include_path is a colon-separated list of directories to search.
-+ *
-+ * and finally we pass in the current request time so we can avoid
-+ * caching files with a current mtime which tends to indicate that
-+ * they are still being written to.
-+ */
-+extern int apc_cache_make_file_key(apc_cache_key_t* key,
-+                                   const char* filename,
-+                                   const char* include_path,
-+                                   time_t t
-+                                                             TSRMLS_DC);
++    slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
 +
-+/*
-+ * apc_cache_make_file_entry creates an apc_cache_entry_t object given a filename
-+ * and the compilation results returned by the PHP compiler.
-+ */
-+extern apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
-+                                                    zend_op_array* op_array,
-+                                                    apc_function_t* functions,
-+                                                    apc_class_t* classes);
-+/*
-+ * apc_cache_make_user_entry creates an apc_cache_entry_t object given an info string
-+ * and the zval to be stored.
-+ */
-+extern apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval *val, const unsigned int ttl);
++    while (*slot) {
++        if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
++            retval = updater(cache, (*slot)->value, data);
++            (*slot)->key.mtime = apc_time();
++            CACHE_UNLOCK(cache);
++            return retval;
++        }
++        slot = &(*slot)->next;
++    }
++    CACHE_UNLOCK(cache);
++    return 0;
++}
++/* }}} */
 +
-+extern int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t);
++/* {{{ apc_cache_user_delete */
++int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen)
++{
++    slot_t** slot;
 +
-+/*
-+ * Frees all memory associated with an object returned by apc_cache_make_entry
-+ * (see above).
-+ */
-+extern void apc_cache_free_entry(apc_cache_entry_t* entry);
++    CACHE_LOCK(cache);
 +
-+/* {{{ struct definition: apc_cache_link_data_t */
-+typedef union _apc_cache_link_data_t {
-+    struct {
-+        char *filename;
-+        dev_t device;
-+        ino_t inode;
-+    } file;
-+    struct {
-+        char *info;
-+        unsigned int ttl;
-+    } user;
-+} apc_cache_link_data_t;
-+/* }}} */
++    slot = &cache->slots[string_nhash_8(strkey, keylen) % cache->num_slots];
 +
-+/* {{{ struct definition: apc_cache_link_t */
-+typedef struct apc_cache_link_t apc_cache_link_t;
-+struct apc_cache_link_t {
-+    apc_cache_link_data_t data;
-+    unsigned char type;
-+    int num_hits;
-+    time_t mtime;
-+    time_t creation_time;
-+    time_t deletion_time;
-+    time_t access_time;
-+    int ref_count;
-+    size_t mem_size;
-+    apc_cache_link_t* next;
-+};
-+/* }}} */
++    while (*slot) {
++        if (!memcmp((*slot)->key.data.user.identifier, strkey, keylen)) {
++            remove_slot(cache, slot);
++            CACHE_UNLOCK(cache);
++            return 1;
++        }
++        slot = &(*slot)->next;
++    }
 +
-+/* {{{ struct definition: apc_cache_info_t */
-+typedef struct apc_cache_info_t apc_cache_info_t;
-+struct apc_cache_info_t {
-+    int num_slots;
-+    int num_hits;
-+    int num_misses;
-+    int ttl;
-+    apc_cache_link_t* list;
-+    apc_cache_link_t* deleted_list;
-+    time_t start_time;
-+    int expunges;
-+    int num_entries;
-+    int num_inserts;
-+    size_t mem_size;
-+};
++    CACHE_UNLOCK(cache);
++    return 0;
++}
 +/* }}} */
 +
-+extern apc_cache_info_t* apc_cache_info(T cache, zend_bool limited);
-+extern void apc_cache_free_info(apc_cache_info_t* info);
-+extern void apc_cache_expunge(apc_cache_t* cache, time_t t);
-+extern void apc_cache_unlock(apc_cache_t* cache);
-+extern zend_bool apc_cache_busy(apc_cache_t* cache);
-+extern zend_bool apc_cache_write_lock(apc_cache_t* cache);
-+extern void apc_cache_write_unlock(apc_cache_t* cache);
-+
-+/* 
-+ * Process local cache, which keeps a refcount hungry version of the slots
-+ * for quick access without a lock - as long as the entry exists in local
-+ * cache, the refcount of the shm version will be +1 more than required.
-+ * It holds no data, only a shallow copy of apc_cache_entry.
-+ */
-+typedef struct apc_local_cache_t apc_local_cache_t; /* process-local cache */ 
-+
-+extern apc_local_cache_t* apc_local_cache_create(apc_cache_t *shmcache, int num_slots, int ttl);
-+extern apc_cache_entry_t* apc_local_cache_find(apc_local_cache_t* cache, apc_cache_key_t key, time_t t);
-+extern void apc_local_cache_destroy(apc_local_cache_t* cache);
-+extern void apc_local_cache_cleanup(apc_local_cache_t* cache);
-+
-+#undef T
-+#endif
-+
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_compile.c php-5.2.5/ext/apc/apc_compile.c
---- php-5.2.5-orig/ext/apc/apc_compile.c       1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_compile.c    2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,2529 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt.                                 |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
-+  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
-+  +----------------------------------------------------------------------+
++/* {{{ apc_cache_delete */
++int apc_cache_delete(apc_cache_t* cache, char *filename, int filename_len)
++{
++    slot_t** slot;
++    time_t t;
++    apc_cache_key_t key;
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++    TSRMLS_FETCH();
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++    t = apc_time();
 +
-+ */
++    /* try to create a cache key; if we fail, give up on caching */
++    if (!apc_cache_make_file_key(&key, filename, PG(include_path), t TSRMLS_CC)) {
++        apc_wprint("Could not stat file %s, unable to delete from cache.", filename);
++        return -1;
++    }
 +
-+/* $Id: apc_compile.c,v 3.87 2007/08/25 13:09:13 gopalv Exp $ */
++    CACHE_LOCK(cache);
 +
-+#include "apc_compile.h"
-+#include "apc_globals.h"
-+#include "apc_zend.h"
++    if(key.type == APC_CACHE_KEY_FILE) slot = &cache->slots[hash(key) % cache->num_slots];
++    else slot = &cache->slots[string_nhash_8(key.data.fpfile.fullpath, key.data.fpfile.fullpath_len) % cache->num_slots];
 +
-+typedef void* (*ht_copy_fun_t)(void*, void*, apc_malloc_t, apc_free_t);
-+typedef void  (*ht_free_fun_t)(void*, apc_free_t);
-+typedef int (*ht_check_copy_fun_t)(Bucket*, va_list);
++    while(*slot) {
++      if(key.type == (*slot)->key.type) {
++        if(key.type == APC_CACHE_KEY_FILE) {
++            if(key_equals((*slot)->key.data.file, key.data.file)) {
++                remove_slot(cache, slot);
++                CACHE_UNLOCK(cache);
++                return 1;
++            }
++        } else {   /* APC_CACHE_KEY_FPFILE */
++            if(!memcmp((*slot)->key.data.fpfile.fullpath, key.data.fpfile.fullpath, key.data.fpfile.fullpath_len+1)) {
++                remove_slot(cache, slot);
++                CACHE_UNLOCK(cache);
++                return 1;
++            }
++        }
++      }
++      slot = &(*slot)->next;
++    }
 +
-+#ifdef ZEND_ENGINE_2
-+typedef void (*ht_fixup_fun_t)(Bucket*, zend_class_entry*, zend_class_entry*);
-+#endif
++    CACHE_UNLOCK(cache);
++    return 0;
 +
-+#define CHECK(p) { if ((p) == NULL) return NULL; }
++}
++/* }}} */
 +
-+/* {{{ internal function declarations */
++/* {{{ apc_cache_release */
++void apc_cache_release(apc_cache_t* cache, apc_cache_entry_t* entry)
++{
++    CACHE_LOCK(cache);
++    entry->ref_count--;
++    CACHE_UNLOCK(cache);
++}
++/* }}} */
 +
-+static int is_derived_class(zend_op_array* op_array, const char* key, int key_size);
++/* {{{ apc_cache_make_file_key */
++int apc_cache_make_file_key(apc_cache_key_t* key,
++                       const char* filename,
++                       const char* include_path,
++                       time_t t
++                       TSRMLS_DC)
++{
++    struct stat *tmp_buf=NULL;
++    struct apc_fileinfo_t fileinfo = { {0}, };
++    int len;
 +
-+static zend_function* my_bitwise_copy_function(zend_function*, zend_function*, apc_malloc_t);
++    assert(key != NULL);
 +
-+/*
-+ * The "copy" functions perform deep-copies on a particular data structure
-+ * (passed as the second argument). They also optionally allocate space for
-+ * the destination data structure if the first argument is null.
-+ */
-+static zval** my_copy_zval_ptr(zval**, const zval**, apc_malloc_t, apc_free_t);
-+static zval* my_copy_zval(zval*, const zval*, apc_malloc_t, apc_free_t);
-+static znode* my_copy_znode(znode*, znode*, apc_malloc_t, apc_free_t);
-+static zend_op* my_copy_zend_op(zend_op*, zend_op*, apc_malloc_t, apc_free_t);
-+static zend_function* my_copy_function(zend_function*, zend_function*, apc_malloc_t, apc_free_t);
-+static zend_function_entry* my_copy_function_entry(zend_function_entry*, zend_function_entry*, apc_malloc_t, apc_free_t);
-+static zend_class_entry* my_copy_class_entry(zend_class_entry*, zend_class_entry*, apc_malloc_t, apc_free_t);
-+static HashTable* my_copy_hashtable_ex(HashTable*, HashTable*, ht_copy_fun_t, ht_free_fun_t, int, apc_malloc_t, apc_free_t, ht_check_copy_fun_t, ...);
-+#define my_copy_hashtable( dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate) \
-+    my_copy_hashtable_ex(dst, src, copy_fn, free_fn, holds_ptr, allocate, deallocate, NULL)
-+static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate);
-+#ifdef ZEND_ENGINE_2
-+static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate);
-+static zend_arg_info* my_copy_arg_info_array(zend_arg_info*, zend_arg_info*, uint, apc_malloc_t, apc_free_t);
-+static zend_arg_info* my_copy_arg_info(zend_arg_info*, zend_arg_info*, apc_malloc_t, apc_free_t);
-+#endif
-+/*
-+ * The "destroy" functions free the memory associated with a particular data
-+ * structure but do not free the pointer to the data structure.
-+ *
-+ * my_destroy_zval() returns SUCCESS or FAILURE, FAILURE means that
-+ * the zval* has other references elsewhere 
-+ */
-+static int  my_destroy_zval(zval*, apc_free_t); 
-+static void my_destroy_zval_ptr(zval**, apc_free_t);
-+static void my_destroy_zend_op(zend_op*, apc_free_t);
-+static void my_destroy_znode(znode*, apc_free_t);
-+static void my_destroy_function(zend_function*, apc_free_t);
-+static void my_destroy_function_entry(zend_function_entry*, apc_free_t);
-+static void my_destroy_class_entry(zend_class_entry*, apc_free_t);
-+static void my_destroy_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
-+static void my_destroy_op_array(zend_op_array*, apc_free_t);
-+#ifdef ZEND_ENGINE_2
-+static void my_destroy_property_info(zend_property_info*, apc_free_t);
-+static void my_destroy_arg_info_array(zend_arg_info* src, uint, apc_free_t);
-+static void my_destroy_arg_info(zend_arg_info*, apc_free_t);
++    if (!filename || !SG(request_info).path_translated) {
++#ifdef __DEBUG_APC__
++        fprintf(stderr,"No filename and no path_translated - bailing\n");
 +#endif
++        return 0;
++    }
 +
-+/*
-+ * The "free" functions work exactly like their "destroy" counterparts (see
-+ * above) but also free the pointer to the data structure.
-+ */
-+static void my_free_zval_ptr(zval**, apc_free_t);
-+static void my_free_function(zend_function*, apc_free_t);
-+static void my_free_hashtable(HashTable*, ht_free_fun_t, apc_free_t);
-+#ifdef ZEND_ENGINE_2
-+static void my_free_property_info(zend_property_info* src, apc_free_t);
-+static void my_free_arg_info_array(zend_arg_info*, uint, apc_free_t);
-+static void my_free_arg_info(zend_arg_info*, apc_free_t);
-+#endif
++    len = strlen(filename);
++    if(APCG(fpstat)==0) {
++        if(IS_ABSOLUTE_PATH(filename,len)) {
++            key->data.fpfile.fullpath = filename;
++            key->data.fpfile.fullpath_len = len;
++            key->mtime = t;
++            key->type = APC_CACHE_KEY_FPFILE;
++            return 1;
++        } else if(APCG(canonicalize)) {
++            if (apc_search_paths(filename, include_path, &fileinfo) != 0) {
++                apc_wprint("apc failed to locate %s - bailing", filename);
++                return 0;
++            }
 +
-+/*
-+ * The "fixup" functions need for ZEND_ENGINE_2
-+ */
-+#ifdef ZEND_ENGINE_2
-+static void my_fixup_function( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
-+static void my_fixup_hashtable( HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst );
-+/* my_fixup_function_for_execution is the same as my_fixup_function
-+ * but named differently for clarity
-+ */
-+#define my_fixup_function_for_execution my_fixup_function
++            if(!realpath(fileinfo.fullpath, APCG(canon_path))) {
++                apc_wprint("realpath failed to canonicalize %s - bailing", filename);
++                return 0;
++            }
 +
-+#ifdef ZEND_ENGINE_2_2
-+static void my_fixup_property_info( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
-+#define my_fixup_property_info_for_execution my_fixup_property_info
++            key->data.fpfile.fullpath = APCG(canon_path);
++            key->data.fpfile.fullpath_len = strlen(APCG(canon_path));
++            key->mtime = t;
++            key->type = APC_CACHE_KEY_FPFILE;
++            return 1;
++        }
++        /* fall through to stat mode */
++    }
++
++    if(!strcmp(SG(request_info).path_translated, filename)) {
++        tmp_buf = sapi_get_stat(TSRMLS_C);  /* Apache has already done this stat() for us */
++    }
++    if(tmp_buf) {
++        fileinfo.st_buf.sb = *tmp_buf;
++    } else {
++        if (apc_search_paths(filename, include_path, &fileinfo) != 0) {
++#ifdef __DEBUG_APC__
++            fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated);
 +#endif
++            return 0;
++        }
++    }
 +
++    if(APCG(max_file_size) < fileinfo.st_buf.sb.st_size) {
++#ifdef __DEBUG_APC__
++        fprintf(stderr,"File is too big %s (%d - %ld) - bailing\n",filename,t,fileinfo.st_buf.sb.st_size);
 +#endif
++        return 0;
++    }
 +
-+/*
-+ * These functions return "1" if the member/function is
-+ * defined/overridden in the 'current' class and not inherited.
-+ */
-+static int my_check_copy_function(Bucket* src, va_list args);
-+static int my_check_copy_default_property(Bucket* p, va_list args);
-+#ifdef ZEND_ENGINE_2
-+static int my_check_copy_property_info(Bucket* src, va_list args);
-+static int my_check_copy_static_member(Bucket* src, va_list args);
++    /*
++     * This is a bit of a hack.
++     *
++     * Here I am checking to see if the file is at least 2 seconds old.  
++     * The idea is that if the file is currently being written to then its
++     * mtime is going to match or at most be 1 second off of the current
++     * request time and we want to avoid caching files that have not been
++     * completely written.  Of course, people should be using atomic 
++     * mechanisms to push files onto live web servers, but adding this
++     * tiny safety is easier than educating the world.  This is now
++     * configurable, but the default is still 2 seconds.
++     */
++    if(APCG(file_update_protection) && (t - fileinfo.st_buf.sb.st_mtime < APCG(file_update_protection)) && !APCG(force_file_update)) {
++#ifdef __DEBUG_APC__
++        fprintf(stderr,"File is too new %s (%d - %d) - bailing\n",filename,t,fileinfo.st_buf.sb.st_mtime);
 +#endif
++        return 0;
++    }
 +
++    key->data.file.device = fileinfo.st_buf.sb.st_dev;
++    key->data.file.inode  = fileinfo.st_buf.sb.st_ino;
++    /*
++     * If working with content management systems that like to munge the mtime, 
++     * it might be appropriate to key off of the ctime to be immune to systems
++     * that try to backdate a template.  If the mtime is set to something older
++     * than the previous mtime of a template we will obviously never see this
++     * "older" template.  At some point the Smarty templating system did this.
++     * I generally disagree with using the ctime here because you lose the 
++     * ability to warm up new content by saving it to a temporary file, hitting
++     * it once to cache it and then renaming it into its permanent location so
++     * set the apc.stat_ctime=true to enable this check.
++     */
++    if(APCG(stat_ctime)) {
++        key->mtime  = (fileinfo.st_buf.sb.st_ctime > fileinfo.st_buf.sb.st_mtime) ? fileinfo.st_buf.sb.st_ctime : fileinfo.st_buf.sb.st_mtime; 
++    } else {
++        key->mtime = fileinfo.st_buf.sb.st_mtime;
++    }
++    key->type = APC_CACHE_KEY_FILE;
++    return 1;
++}
 +/* }}} */
 +
-+/* {{{ check_op_array_integrity */
-+#if 0
-+static void check_op_array_integrity(zend_op_array* src)
++/* {{{ apc_cache_make_user_key */
++int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t)
 +{
-+    int i, j;
-+
-+    /* These sorts of checks really aren't particularly effective, but they
-+     * can provide a welcome sanity check when debugging. Just don't enable
-+     * for production use!  */
++    assert(key != NULL);
 +
-+    assert(src->refcount != NULL);
-+    assert(src->opcodes != NULL);
-+    assert(src->last > 0);
++    if (!identifier)
++        return 0;
 +
-+    for (i = 0; i < src->last; i++) {
-+        zend_op* op = &src->opcodes[i];
-+        znode* nodes[] = { &op->result, &op->op1, &op->op2 };
-+        for (j = 0; j < 3; j++) {
-+            assert(nodes[j]->op_type == IS_CONST ||
-+                   nodes[j]->op_type == IS_VAR ||
-+                   nodes[j]->op_type == IS_TMP_VAR ||
-+                   nodes[j]->op_type == IS_UNUSED);
-+
-+            if (nodes[j]->op_type == IS_CONST) {
-+                int type = nodes[j]->u.constant.type;
-+                assert(type == IS_RESOURCE ||
-+                       type == IS_BOOL ||
-+                       type == IS_LONG ||
-+                       type == IS_DOUBLE ||
-+                       type == IS_NULL ||
-+                       type == IS_CONSTANT ||
-+                       type == IS_STRING ||
-+                       type == FLAG_IS_BC ||
-+                       type == IS_ARRAY ||
-+                       type == IS_CONSTANT_ARRAY ||
-+                       type == IS_OBJECT);
-+            }
-+        }
-+    }
++    key->data.user.identifier = identifier;
++    key->data.user.identifier_len = identifier_len;
++    key->mtime = t;
++    key->type = APC_CACHE_KEY_USER;
++    return 1;
 +}
-+#endif
 +/* }}} */
 +
-+/* {{{ is_derived_class */
-+static int is_derived_class(zend_op_array* op_array, const char* key, int key_size)
++/* {{{ apc_cache_make_file_entry */
++apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
++                                        zend_op_array* op_array,
++                                        apc_function_t* functions,
++                                        apc_class_t* classes,
++                                        apc_context_t* ctxt)
 +{
-+    int i;
++    apc_cache_entry_t* entry;
++    apc_pool* pool = ctxt->pool;
 +
-+    /*
-+     * Scan the op_array for execution-time class declarations of derived
-+     * classes. If we find one whose key matches our current class key, we
-+     * know the current class is a derived class.
-+     *
-+     * This check is exceedingly inefficient (fortunately it only has to occur
-+     * once, when the source file is first compiled and cached), but the
-+     * compiler should save this information for us -- definitely a candidate
-+     * for a Zend Engine patch.
-+     *
-+     * XXX checking for derived classes provides a minimal (albeit measurable)
-+     * speed up. It may not be worth the added complexity -- considere
-+     * removing this optimization.
-+     */
++    entry = (apc_cache_entry_t*) apc_pool_alloc(pool, sizeof(apc_cache_entry_t));
++    if (!entry) return NULL;
 +
-+    for (i = 0; i < op_array->last; i++) {
-+        zend_op* op = &op_array->opcodes[i];
-+
-+#ifdef ZEND_ENGINE_2        
-+        if (op->opcode == ZEND_DECLARE_CLASS &&
-+            op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
-+#else            
-+        if (op->opcode == ZEND_DECLARE_FUNCTION_OR_CLASS &&
-+            op->extended_value == ZEND_DECLARE_INHERITED_CLASS)
-+#endif            
-+        {
-+            if (op->op1.u.constant.value.str.len == key_size &&
-+                !memcmp(op->op1.u.constant.value.str.val, key, key_size))
-+            {
-+                return 1;
-+            }
-+        }
++    entry->data.file.filename  = apc_pstrdup(filename, pool);
++    if(!entry->data.file.filename) {
++#ifdef __DEBUG_APC__
++        fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is NULL - bailing\n");
++#endif
++        return NULL;
 +    }
++#ifdef __DEBUG_APC__
++    fprintf(stderr,"apc_cache_make_file_entry: entry->data.file.filename is [%s]\n",entry->data.file.filename);
++#endif
++    entry->data.file.op_array  = op_array;
++    entry->data.file.functions = functions;
++    entry->data.file.classes   = classes;
 +
-+    return 0;
++    entry->data.file.halt_offset = apc_file_halt_offset(filename);
++
++    entry->type = APC_CACHE_ENTRY_FILE;
++    entry->ref_count = 0;
++    entry->mem_size = 0;
++    entry->pool = pool;
++    return entry;
 +}
 +/* }}} */
 +
-+/* {{{ my_bitwise_copy_function */
-+static zend_function* my_bitwise_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate)
++/* {{{ apc_cache_store_zval */
++zval* apc_cache_store_zval(zval* dst, const zval* src, apc_context_t* ctxt)
 +{
-+    assert(src != NULL);
++    TSRMLS_FETCH();
 +
-+    if (!dst) {
-+        CHECK(dst = (zend_function*) allocate(sizeof(src[0])));
++    if (Z_TYPE_P(src) == IS_ARRAY) {
++        /* Maintain a list of zvals we've copied to properly handle recursive structures */
++        zend_hash_init(&APCG(copied_zvals), 0, NULL, NULL, 0);
++        dst = apc_copy_zval(dst, src, ctxt);
++        zend_hash_destroy(&APCG(copied_zvals));
++        APCG(copied_zvals).nTableSize=0;
++    } else {
++        dst = apc_copy_zval(dst, src, ctxt);
 +    }
 +
-+    /* We only need to do a bitwise copy */
-+    memcpy(dst, src, sizeof(src[0]));
 +
 +    return dst;
 +}
 +/* }}} */
 +
-+/* {{{ my_copy_zval_ptr */
-+static zval** my_copy_zval_ptr(zval** dst, const zval** src, apc_malloc_t allocate, apc_free_t deallocate)
++/* {{{ apc_cache_fetch_zval */
++zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_context_t* ctxt)
 +{
-+    int local_dst_alloc = 0;
-+    zval* dst_new;
-+    
-+    assert(src != NULL);
++    TSRMLS_FETCH();
 +
-+    if (!dst) {
-+        CHECK(dst = (zval**) allocate(sizeof(zval*)));
-+        local_dst_alloc = 1;
++    if (Z_TYPE_P(src) == IS_ARRAY) {
++        /* Maintain a list of zvals we've copied to properly handle recursive structures */
++        zend_hash_init(&APCG(copied_zvals), 0, NULL, NULL, 0);
++        dst = apc_copy_zval(dst, src, ctxt);
++        zend_hash_destroy(&APCG(copied_zvals));
++        APCG(copied_zvals).nTableSize=0;
++    } else {
++        dst = apc_copy_zval(dst, src, ctxt);
 +    }
 +
-+    if(!(dst[0] = (zval*) allocate(sizeof(zval)))) {
-+        if(local_dst_alloc) deallocate(dst);
-+        return NULL;
-+    }
-+    dst_new = my_copy_zval(*dst, *src, allocate, deallocate);
-+    if(dst_new != *dst) {
-+        deallocate(*dst);
-+        *dst = dst_new;
-+    }
 +
-+    (*dst)->refcount = (*src)->refcount;
-+    (*dst)->is_ref = (*src)->is_ref;
-+    
 +    return dst;
 +}
 +/* }}} */
 +
-+/* {{{ my_copy_zval */
-+static zval* my_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
++/* {{{ apc_cache_make_user_entry */
++apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval* val, apc_context_t* ctxt, const unsigned int ttl)
 +{
-+    zval **tmp;
-+    TSRMLS_FETCH();
-+    
-+    assert(dst != NULL);
-+    assert(src != NULL);
-+
-+    memcpy(dst, src, sizeof(src[0]));
++    apc_cache_entry_t* entry;
++    apc_pool* pool = ctxt->pool;
 +
-+    switch (src->type & ~IS_CONSTANT_INDEX) {
-+    case IS_RESOURCE:
-+    case IS_BOOL:
-+    case IS_LONG:
-+    case IS_DOUBLE:
-+    case IS_NULL:
-+        break;
++    entry = (apc_cache_entry_t*) apc_pool_alloc(pool, sizeof(apc_cache_entry_t));
++    if (!entry) return NULL;
 +
-+    case IS_CONSTANT:
-+    case IS_STRING:
-+#ifndef ZEND_ENGINE_2        
-+    case FLAG_IS_BC:
-+#endif        
-+        if (src->value.str.val) {
-+            CHECK(dst->value.str.val = apc_xmemcpy(src->value.str.val,
-+                                                   src->value.str.len+1,
-+                                                   allocate));
-+        }
-+        break;
-+    
-+    case IS_ARRAY:
++    entry->data.user.info = apc_pmemcpy(info, info_len+1, pool);
++    entry->data.user.info_len = info_len;
++    if(!entry->data.user.info) {
++        return NULL;
++    }
++    entry->data.user.val = apc_cache_store_zval(NULL, val, ctxt);
++    if(!entry->data.user.val) {
++        return NULL;
++    }
++    INIT_PZVAL(entry->data.user.val);
++    entry->data.user.ttl = ttl;
++    entry->type = APC_CACHE_ENTRY_USER;
++    entry->ref_count = 0;
++    entry->mem_size = 0;
++    entry->pool = pool;
++    return entry;
++}
++/* }}} */
 +
-+        if(APCG(copied_zvals)) {
-+            if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
-+                (*tmp)->refcount++;
-+                return *tmp;
-+            }
-+        
-+            zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&dst, sizeof(zval*), NULL);
-+        }
-+        /* fall through */
-+ 
-+    case IS_CONSTANT_ARRAY:
++/* {{{ apc_cache_info */
++apc_cache_info_t* apc_cache_info(apc_cache_t* cache, zend_bool limited)
++{
++    apc_cache_info_t* info;
++    slot_t* p;
++    int i;
 +
-+        CHECK(dst->value.ht =
-+            my_copy_hashtable(NULL,
-+                              src->value.ht,
-+                              (ht_copy_fun_t) my_copy_zval_ptr,
-+                              (ht_free_fun_t) my_free_zval_ptr,
-+                              1,
-+                              allocate, deallocate));
-+        break;
++      TSRMLS_FETCH();
 +
-+    case IS_OBJECT:
-+#ifndef ZEND_ENGINE_2        
-+        CHECK(dst->value.obj.ce =
-+            my_copy_class_entry(NULL, src->value.obj.ce, allocate, deallocate));
++    if(!cache) return NULL;
 +
-+        if(!(dst->value.obj.properties = my_copy_hashtable(NULL,
-+                              src->value.obj.properties,
-+                              (ht_copy_fun_t) my_copy_zval_ptr,
-+                              (ht_free_fun_t) my_free_zval_ptr,
-+                              1,
-+                              allocate, deallocate))) {
-+            my_destroy_class_entry(dst->value.obj.ce, deallocate);
-+            return NULL;
-+        }
-+        break;
-+#else
-+      dst->type = IS_NULL;
-+#endif        
-+        break;
++    CACHE_LOCK(cache);
 +
-+    default:
-+        assert(0);
++    info = (apc_cache_info_t*) apc_emalloc(sizeof(apc_cache_info_t));
++    if(!info) {
++        CACHE_UNLOCK(cache);
++        return NULL;
 +    }
++    info->num_slots = cache->num_slots;
++    info->ttl = cache->ttl;
++    info->num_hits = cache->header->num_hits;
++    info->num_misses = cache->header->num_misses;
++    info->list = NULL;
++    info->deleted_list = NULL;
++    info->start_time = cache->header->start_time;
++    info->expunges = cache->header->expunges;
++    info->mem_size = cache->header->mem_size;
++    info->num_entries = cache->header->num_entries;
++    info->num_inserts = cache->header->num_inserts;
 +
-+    return dst;
-+}
-+/* }}} */
-+
-+/* {{{ my_copy_znode */
-+static znode* my_copy_znode(znode* dst, znode* src, apc_malloc_t allocate, apc_free_t deallocate)
-+{
-+    assert(dst != NULL);
-+    assert(src != NULL);
++    if(!limited) {
++        /* For each hashtable slot */
++        for (i = 0; i < info->num_slots; i++) {
++            p = cache->slots[i];
++            for (; p != NULL; p = p->next) {
++                apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
 +
-+    memcpy(dst, src, sizeof(src[0]));
++                if(p->value->type == APC_CACHE_ENTRY_FILE) {
++                    if(p->key.type == APC_CACHE_KEY_FILE) {
++                        link->data.file.device = p->key.data.file.device;
++                        link->data.file.inode = p->key.data.file.inode;
++                        link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
++                    } else { /* This is a no-stat fullpath file entry */
++                        link->data.file.device = 0;
++                        link->data.file.inode = 0;
++                        link->data.file.filename = apc_xstrdup(p->key.data.fpfile.fullpath, apc_emalloc);
++                    }
++                    link->type = APC_CACHE_ENTRY_FILE;
++                    if (APCG(file_md5)) {
++                      link->data.file.md5 = emalloc(sizeof(p->key.md5));
++                      memcpy(link->data.file.md5, p->key.md5, 16);
++                    } else {
++                      link->data.file.md5 = NULL;
++                    }
++                } else if(p->value->type == APC_CACHE_ENTRY_USER) {
++                    link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len+1, apc_emalloc);
++                    link->data.user.ttl = p->value->data.user.ttl;
++                    link->type = APC_CACHE_ENTRY_USER;
++                }
++                link->num_hits = p->num_hits;
++                link->mtime = p->key.mtime;
++                link->creation_time = p->creation_time;
++                link->deletion_time = p->deletion_time;
++                link->access_time = p->access_time;
++                link->ref_count = p->value->ref_count;
++                link->mem_size = p->value->mem_size;
++                link->next = info->list;
++                info->list = link;
++            }
++        }
 +
-+#ifdef IS_CV
-+    assert(dst ->op_type == IS_CONST ||
-+           dst ->op_type == IS_VAR ||
-+           dst ->op_type == IS_CV ||
-+           dst ->op_type == IS_TMP_VAR ||
-+           dst ->op_type == IS_UNUSED);
-+#else
-+    assert(dst ->op_type == IS_CONST ||
-+           dst ->op_type == IS_VAR ||
-+           dst ->op_type == IS_TMP_VAR ||
-+           dst ->op_type == IS_UNUSED);
-+#endif
++        /* For each slot pending deletion */
++        for (p = cache->header->deleted_list; p != NULL; p = p->next) {
++            apc_cache_link_t* link = (apc_cache_link_t*) apc_emalloc(sizeof(apc_cache_link_t));
 +
-+    if (src->op_type == IS_CONST) {
-+        if(!my_copy_zval(&dst->u.constant, &src->u.constant, allocate, deallocate)) {
-+            return NULL;
++            if(p->value->type == APC_CACHE_ENTRY_FILE) {
++                if(p->key.type == APC_CACHE_KEY_FILE) {
++                    link->data.file.device = p->key.data.file.device;
++                    link->data.file.inode = p->key.data.file.inode;
++                    link->data.file.filename = apc_xstrdup(p->value->data.file.filename, apc_emalloc);
++                } else { /* This is a no-stat fullpath file entry */
++                    link->data.file.device = 0;
++                    link->data.file.inode = 0;
++                    link->data.file.filename = apc_xstrdup(p->key.data.fpfile.fullpath, apc_emalloc);
++                }
++                link->type = APC_CACHE_ENTRY_FILE;
++                if (APCG(file_md5)) {
++                  link->data.file.md5 = emalloc(sizeof(p->key.md5));
++                  memcpy(link->data.file.md5, p->key.md5, 16);
++                } else {
++                  link->data.file.md5 = NULL;
++                }
++            } else if(p->value->type == APC_CACHE_ENTRY_USER) {
++                link->data.user.info = apc_xmemcpy(p->value->data.user.info, p->value->data.user.info_len+1, apc_emalloc);
++                link->data.user.ttl = p->value->data.user.ttl;
++                link->type = APC_CACHE_ENTRY_USER;
++            }
++            link->num_hits = p->num_hits;
++            link->mtime = p->key.mtime;
++            link->creation_time = p->creation_time;
++            link->deletion_time = p->deletion_time;
++            link->access_time = p->access_time;
++            link->ref_count = p->value->ref_count;
++            link->mem_size = p->value->mem_size;
++            link->next = info->deleted_list;
++            info->deleted_list = link;
 +        }
 +    }
 +
-+    return dst;
++    CACHE_UNLOCK(cache);
++    return info;
 +}
 +/* }}} */
 +
-+/* {{{ my_copy_zend_op */
-+static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_malloc_t allocate, apc_free_t deallocate)
++/* {{{ apc_cache_free_info */
++void apc_cache_free_info(apc_cache_info_t* info)
 +{
-+    assert(dst != NULL);
-+    assert(src != NULL);
-+
-+    memcpy(dst, src, sizeof(src[0]));
-+
-+    if( my_copy_znode(&dst->result, &src->result, allocate, deallocate) == NULL 
-+            || my_copy_znode(&dst->op1, &src->op1, allocate, deallocate) == NULL
-+            || my_copy_znode(&dst->op2, &src->op2, allocate, deallocate) == NULL)
-+    {
-+        return NULL;
++    apc_cache_link_t* p = info->list;
++    apc_cache_link_t* q = NULL;
++    while (p != NULL) {
++        q = p;
++        p = p->next;
++        if(q->type == APC_CACHE_ENTRY_FILE) {
++            if(q->data.file.md5) {
++                efree(q->data.file.md5);
++            }
++            apc_efree(q->data.file.filename);
++        }
++        else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
++        apc_efree(q);
 +    }
-+
-+    return dst;
++    p = info->deleted_list;
++    while (p != NULL) {
++        q = p;
++        p = p->next;
++        if(q->type == APC_CACHE_ENTRY_FILE) {
++            if(q->data.file.md5) {
++                efree(q->data.file.md5);
++            }
++            apc_efree(q->data.file.filename);
++        }
++        else if(q->type == APC_CACHE_ENTRY_USER) apc_efree(q->data.user.info);
++        apc_efree(q);
++    }
++    apc_efree(info);
 +}
 +/* }}} */
 +
-+/* {{{ my_copy_function */
-+static zend_function* my_copy_function(zend_function* dst, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
++/* {{{ apc_cache_unlock */
++void apc_cache_unlock(apc_cache_t* cache)
 +{
-+    int local_dst_alloc = 0;
-+      TSRMLS_FETCH();
-+
-+    assert(src != NULL);
-+
-+    if(!dst) local_dst_alloc = 1;
-+    CHECK(dst = my_bitwise_copy_function(dst, src, allocate));
-+
-+    switch (src->type) {
-+    case ZEND_INTERNAL_FUNCTION:
-+    case ZEND_OVERLOADED_FUNCTION:
-+        /* shallow copy because op_array is internal */
-+        dst->op_array = src->op_array;
-+        break;
-+        
-+    case ZEND_USER_FUNCTION:
-+    case ZEND_EVAL_CODE:
-+        if(!apc_copy_op_array(&dst->op_array,
-+                                &src->op_array,
-+                                allocate, deallocate TSRMLS_CC)) {
-+            if(local_dst_alloc) deallocate(dst);
-+            return NULL;
-+        }
-+        break;
-+
-+    default:
-+        assert(0);
-+    }
-+#ifdef ZEND_ENGINE_2
-+    /* 
-+     * op_array bitwise copying overwrites what ever you modified
-+     * before apc_copy_op_array - which is why this code is outside 
-+     * my_bitwise_copy_function. 
-+     */
-+
-+    /* zend_do_inheritance will re-look this up, because the pointers
-+     * in prototype are from a function table of another class. It just
-+     * helps if that one is from EG(class_table).
-+     */
-+    dst->common.prototype = NULL; 
-+
-+    /* once a method is marked as ZEND_ACC_IMPLEMENTED_ABSTRACT then you
-+     * have to carry around a prototype. Thankfully zend_do_inheritance
-+     * sets this properly as well
-+     */
-+    dst->common.fn_flags = src->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
-+#endif
-+
-+
-+    return dst;
++    CACHE_UNLOCK(cache);
 +}
 +/* }}} */
 +
-+/* {{{ my_copy_function_entry */
-+static zend_function_entry* my_copy_function_entry(zend_function_entry* dst, zend_function_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
++/* {{{ apc_cache_busy */
++zend_bool apc_cache_busy(apc_cache_t* cache)
 +{
-+    int local_dst_alloc = 0;
-+    assert(src != NULL);
-+
-+    if (!dst) {
-+        CHECK(dst = (zend_function_entry*) allocate(sizeof(src[0])));
-+        local_dst_alloc = 1;
-+    }
-+
-+    /* Start with a bitwise copy */
-+    memcpy(dst, src, sizeof(src[0]));
-+
-+    dst->fname = NULL;
-+#ifdef ZEND_ENGINE_2
-+    dst->arg_info = NULL;
-+#else
-+    dst->func_arg_types = NULL;
-+#endif
-+
-+    if (src->fname) {
-+        if(!(dst->fname = apc_xstrdup(src->fname, allocate))) {
-+            goto cleanup;
-+        }
-+    }
-+
-+#ifdef ZEND_ENGINE_2    
-+    if (src->arg_info) {
-+        if(!(dst->arg_info = my_copy_arg_info_array(NULL,
-+                                                src->arg_info,
-+                                                src->num_args,
-+                                                allocate,
-+                                                deallocate))) {
-+            goto cleanup;
-+        }
-+    }
-+#else    
-+    if (src->func_arg_types) {
-+        if(!(dst->func_arg_types = apc_xmemcpy(src->func_arg_types,
-+                                                src->func_arg_types[0]+1,
-+                                                allocate))) {
-+            goto cleanup;
-+        }
-+    }
-+#endif
-+
-+    return dst;
-+
-+cleanup:
-+    if(dst->fname) deallocate(dst->fname);
-+    if(local_dst_alloc) deallocate(dst);
-+    return NULL;
++    return cache->header->busy;
 +}
 +/* }}} */
 +
-+#ifdef ZEND_ENGINE_2
-+/* {{{ my_copy_property_info */
-+static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate)
++/* {{{ apc_cache_is_last_key */
++zend_bool apc_cache_is_last_key(apc_cache_t* cache, apc_cache_key_t* key, time_t t)
 +{
-+    int local_dst_alloc = 0;
-+    
-+    assert(src != NULL);
-+
-+    if (!dst) {
-+        CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
-+        local_dst_alloc = 1;
-+    }
-+
-+    /* Start with a bitwise copy */
-+    memcpy(dst, src, sizeof(*src));
-+
-+    dst->name = NULL;
-+#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
-+    dst->doc_comment = NULL;
-+#endif
-+
-+    if (src->name) {
-+        /* private members are stored inside property_info as a mangled
-+         * string of the form:
-+         *      \0<classname>\0<membername>\0
-+         */
-+        if(!(dst->name = 
-+                    apc_xmemcpy(src->name, src->name_length+1, allocate))) {
-+            goto cleanup;
-+        }
-+    }
-+
-+#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
-+    if (src->doc_comment) {
-+        if( !(dst->doc_comment =
-+                    apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
-+            goto cleanup;
++    apc_keyid_t *lastkey = &cache->header->lastkey;
++    unsigned int keylen = key->data.user.identifier_len+1;
++    unsigned int h = string_nhash_8(key->data.user.identifier, keylen);
++
++    /* unlocked reads, but we're not shooting for 100% success with this */
++    if(lastkey->h == h && keylen == lastkey->keylen) {
++        if(lastkey->mtime == t) {
++            /* potential cache slam */
++            apc_wprint("Potential cache slam averted for key '%s'", key->data.user.identifier);
++            return 1;
 +        }
 +    }
-+#endif
-+
-+    return dst;
 +
-+cleanup:
-+    if(dst->name) deallocate(dst->name);
-+#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
-+    if(dst->doc_comment) deallocate(dst->doc_comment);
-+#endif
-+    if(local_dst_alloc) deallocate(dst);
-+    return NULL;
++    return 0;
 +}
 +/* }}} */
 +
-+/* {{{ my_copy_property_info_for_execution */
-+static zend_property_info* my_copy_property_info_for_execution(zend_property_info* dst, zend_property_info* src, apc_malloc_t allocate, apc_free_t deallocate)
++#if NONBLOCKING_LOCK_AVAILABLE
++/* {{{ apc_cache_write_lock */
++zend_bool apc_cache_write_lock(apc_cache_t* cache)
 +{
-+    int local_dst_alloc = 0;
-+    
-+    assert(src != NULL);
-+
-+    if (!dst) {
-+        CHECK(dst = (zend_property_info*) allocate(sizeof(*src)));
-+        local_dst_alloc = 1;
-+    }
-+
-+    /* We need only a shallow copy */
-+    memcpy(dst, src, sizeof(*src));
-+
-+    return dst;
++    return apc_lck_nb_lock(cache->header->wrlock);
 +}
 +/* }}} */
 +
-+/* {{{ my_copy_arg_info_array */
-+static zend_arg_info* my_copy_arg_info_array(zend_arg_info* dst, zend_arg_info* src, uint num_args, apc_malloc_t allocate, apc_free_t deallocate)
++/* {{{ apc_cache_write_unlock */
++void apc_cache_write_unlock(apc_cache_t* cache)
 +{
-+    int local_dst_alloc = 0;
-+    int i = 0;
-+
-+    
-+    if (!dst) {
-+        CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)*num_args));
-+        local_dst_alloc = 1;
-+    }
-+
-+    /* Start with a bitwise copy */
-+    memcpy(dst, src, sizeof(*src)*num_args);
-+
-+    for(i=0; i < num_args; i++) {
-+        if(!(my_copy_arg_info( &dst[i], &src[i], allocate, deallocate))) {            
-+            if(i) my_destroy_arg_info_array(dst, i-1, deallocate);
-+            if(local_dst_alloc) deallocate(dst);
-+            return NULL;
-+        }
-+    }
-+
-+    return dst;    
++    apc_lck_unlock(cache->header->wrlock);
 +}
 +/* }}} */
++#endif
 +
-+/* {{{ my_copy_arg_info */
-+static zend_arg_info* my_copy_arg_info(zend_arg_info* dst, zend_arg_info* src, apc_malloc_t allocate, apc_free_t deallocate)
-+{
-+    int local_dst_alloc = 0;
-+    
-+    assert(src != NULL);
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_cache.h php-5.3.1/ext/apc/apc_cache.h
+--- php-5.3.1.orig/ext/apc/apc_cache.h 1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_cache.h      1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,378 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt.                                 |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          Rasmus Lerdorf <rasmus@php.net>                             |
++  +----------------------------------------------------------------------+
 +
-+    if (!dst) {
-+        CHECK(dst = (zend_arg_info*) allocate(sizeof(*src)));
-+        local_dst_alloc = 1;
-+    }
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
 +
-+    /* Start with a bitwise copy */
-+    memcpy(dst, src, sizeof(*src));
++   All other licensing and usage conditions are those of the PHP Group.
 +
-+    dst->name = NULL;
-+    dst->class_name = NULL;
++ */
 +
-+    if (src->name) {
-+        if(!(dst->name = 
-+                    apc_xmemcpy(src->name, src->name_len+1, allocate))) {
-+            goto cleanup;
-+        }
-+    }
++/* $Id: apc_cache.h 281919 2009-06-10 11:23:55Z gopalv $ */
 +
-+    if (src->class_name) {
-+        if(!(dst->class_name = 
-+                    apc_xmemcpy(src->class_name, src->class_name_len+1, allocate))) {
-+            goto cleanup;
-+        }
-+    }
++#ifndef APC_CACHE_H
++#define APC_CACHE_H
 +
-+    return dst;
++/*
++ * This module defines the shared memory file cache. Basically all of the
++ * logic for storing and retrieving cache entries lives here.
++ */
 +
-+cleanup:
-+    if(dst->name) deallocate(dst->name);
-+    if(dst->class_name) deallocate(dst->name);
-+    if(local_dst_alloc) deallocate(dst);
-+    return NULL;
-+}
-+/* }}} */
-+#endif
++#include "apc.h"
++#include "apc_compile.h"
++#include "apc_lock.h"
++#include "apc_pool.h"
++#include "apc_main.h"
 +
-+/* {{{ my_copy_class_entry */
-+static zend_class_entry* my_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate)
-+{
-+    int local_dst_alloc = 0;
-+    int i = 0;
++#define APC_CACHE_ENTRY_FILE   1
++#define APC_CACHE_ENTRY_USER   2
 +
-+    assert(src != NULL);
++#define APC_CACHE_KEY_FILE     1
++#define APC_CACHE_KEY_USER     2
++#define APC_CACHE_KEY_FPFILE   3
 +
-+    if (!dst) {
-+        CHECK(dst = (zend_class_entry*) allocate(sizeof(*src)));
-+        local_dst_alloc = 1;
-+    }
++/* {{{ cache locking macros */
++#define CACHE_LOCK(cache)        { LOCK(cache->header->lock);   cache->has_lock = 1; }
++#define CACHE_UNLOCK(cache)      { UNLOCK(cache->header->lock); cache->has_lock = 0; }
++#define CACHE_SAFE_LOCK(cache)   { if ((++cache->has_lock) == 1) LOCK(cache->header->lock); }
++#define CACHE_SAFE_UNLOCK(cache) { if ((--cache->has_lock) == 0) UNLOCK(cache->header->lock); }
++/* }}} */
 +
-+    /* Start with a bitwise copy */
-+    memcpy(dst, src, sizeof(*src));
++/* {{{ struct definition: apc_cache_key_t */
++#define T apc_cache_t*
++typedef struct apc_cache_t apc_cache_t; /* opaque cache type */
 +
-+    dst->name = NULL;
-+    dst->builtin_functions = NULL;
-+    memset(&dst->function_table, 0, sizeof(dst->function_table));
-+    memset(&dst->default_properties, 0, sizeof(dst->default_properties));
-+#ifndef ZEND_ENGINE_2
-+    dst->refcount = NULL;
-+#else
-+    dst->static_members = NULL;
-+    dst->doc_comment = NULL;
-+    dst->filename = NULL;
-+    memset(&dst->properties_info, 0, sizeof(dst->properties_info));
-+    memset(&dst->constants_table, 0, sizeof(dst->constants_table));
-+    memset(&dst->default_static_members, 0, sizeof(dst->default_static_members));
-+#endif
-+
-+    if (src->name) {
-+        if(!(dst->name = apc_xstrdup(src->name, allocate))) {
-+            goto cleanup;
-+        }
-+    }
-+
-+#ifndef ZEND_ENGINE_2    
-+    if(!(dst->refcount = apc_xmemcpy(src->refcount,
-+                                      sizeof(src->refcount[0]),
-+                                      allocate))) {
-+        goto cleanup;
-+    }
-+#endif        
++typedef union _apc_cache_key_data_t {
++    struct {
++        dev_t device;             /* the filesystem device */
++        ino_t inode;              /* the filesystem inode */
++    } file;
++    struct {
++        const char *identifier;
++        int identifier_len;
++    } user;
++    struct {
++        const char *fullpath;
++        int fullpath_len;
++    } fpfile;
++} apc_cache_key_data_t;
 +
-+    if(!(my_copy_hashtable_ex(&dst->function_table,
-+                            &src->function_table,
-+                            (ht_copy_fun_t) my_copy_function,
-+                            (ht_free_fun_t) my_free_function,
-+                            0,
-+                            allocate, deallocate,
-+                            (ht_check_copy_fun_t) my_check_copy_function,
-+                            src))) {
-+        goto cleanup;
-+    }
++typedef struct apc_cache_key_t apc_cache_key_t;
++struct apc_cache_key_t {
++    apc_cache_key_data_t data;
++    time_t mtime;                 /* the mtime of this cached entry */
++    unsigned char type;
++    unsigned char md5[16];        /* md5 hash of the source file */
++};
 +
-+#ifdef ZEND_ENGINE_2
 +
-+    /* the interfaces are populated at runtime using ADD_INTERFACE */
-+    dst->interfaces = NULL; 
++typedef struct apc_keyid_t apc_keyid_t;
 +
-+    /* the current count includes inherited interfaces as well,
-+       the real dynamic ones are the first <n> which are zero'd
-+       out in zend_do_end_class_declaration */
-+    for(i = 0 ; i < src->num_interfaces ; i++) {
-+        if(src->interfaces[i])
-+        {
-+            dst->num_interfaces = i;
-+            break;
-+        }
-+    }
++struct apc_keyid_t {
++    unsigned int h;
++    unsigned int keylen;
++    time_t mtime;
++};
++/* }}} */
 +
-+    /* these will either be set inside my_fixup_hashtable or 
-+     * they will be copied out from parent inside zend_do_inheritance 
-+     */
-+    dst->constructor =  NULL;
-+    dst->destructor = NULL;
-+    dst->clone = NULL;
-+    dst->__get = NULL;
-+    dst->__set = NULL;
-+    dst->__unset = NULL;
-+    dst->__isset = NULL;
-+    dst->__call = NULL;
-+#ifdef ZEND_ENGINE_2_2
-+    dst->__tostring = NULL;
-+#endif
++/* {{{ struct definition: apc_cache_entry_t */
++typedef union _apc_cache_entry_value_t {
++    struct {
++        char *filename;             /* absolute path to source file */
++        zend_op_array* op_array;    /* op_array allocated in shared memory */
++        apc_function_t* functions;  /* array of apc_function_t's */
++        apc_class_t* classes;       /* array of apc_class_t's */
++        long halt_offset;           /* value of __COMPILER_HALT_OFFSET__ for the file */
++    } file;
++    struct {
++        char *info;
++        int info_len;
++        zval *val;
++        unsigned int ttl;
++    } user;
++} apc_cache_entry_value_t;
 +
-+    /* unset function proxies */
-+    dst->serialize_func = NULL;
-+    dst->unserialize_func = NULL;
-+    
-+    my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function, src, dst);
-+#endif
++typedef struct apc_cache_entry_t apc_cache_entry_t;
++struct apc_cache_entry_t {
++    apc_cache_entry_value_t data;
++    unsigned char type;
++    int ref_count;
++    size_t mem_size;
++    apc_pool *pool;
++};
++/* }}} */
 +
-+    if(!(my_copy_hashtable_ex(&dst->default_properties,
-+                            &src->default_properties,
-+                            (ht_copy_fun_t) my_copy_zval_ptr,
-+                            (ht_free_fun_t) my_free_zval_ptr,
-+                            1,
-+                            allocate,deallocate,
-+                            (ht_check_copy_fun_t) my_check_copy_default_property,
-+                            src))) {
-+        goto cleanup;
-+    }
++/*
++ * apc_cache_create creates the shared memory compiler cache. This function
++ * should be called just once (ideally in the web server parent process, e.g.
++ * in apache), otherwise you will end up with multiple caches (which won't
++ * necessarily break anything). Returns a pointer to the cache object.
++ *
++ * size_hint is a "hint" at the total number of source files that will be
++ * cached. It determines the physical size of the hash table. Passing 0 for
++ * this argument will use a reasonable default value.
++ *
++ * gc_ttl is the maximum time a cache entry may speed on the garbage
++ * collection list. This is basically a work around for the inherent
++ * unreliability of our reference counting mechanism (see apc_cache_release).
++ *
++ * ttl is the maximum time a cache entry can idle in a slot in case the slot
++ * is needed.  This helps in cleaning up the cache and ensuring that entries 
++ * hit frequently stay cached and ones not hit very often eventually disappear.
++ */
++extern T apc_cache_create(int size_hint, int gc_ttl, int ttl);
 +
-+#ifdef ZEND_ENGINE_2
-+    
-+    if(!(my_copy_hashtable_ex(&dst->properties_info,
-+                            &src->properties_info,
-+                            (ht_copy_fun_t) my_copy_property_info,
-+                            (ht_free_fun_t) my_free_property_info,
-+                            0,
-+                            allocate, deallocate,
-+                            (ht_check_copy_fun_t) my_check_copy_property_info,
-+                            src))) {
-+        goto cleanup;
-+    }
++/*
++ * apc_cache_destroy releases any OS resources associated with a cache object.
++ * Under apache, this function can be safely called by the child processes
++ * when they exit.
++ */
++extern void apc_cache_destroy(T cache);
 +
-+#ifdef ZEND_ENGINE_2_2
-+    /* php5.2 introduced a scope attribute for property info */
-+    my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
-+#endif
-+    
-+    if(!my_copy_hashtable_ex(&dst->default_static_members,
-+                            &src->default_static_members,
-+                            (ht_copy_fun_t) my_copy_zval_ptr,
-+                            (ht_free_fun_t) my_free_zval_ptr,
-+                            1,
-+                            allocate, deallocate,
-+                            (ht_check_copy_fun_t) my_check_copy_static_member,
-+                            src,
-+                            &src->default_static_members)) {
-+        goto cleanup;
-+    }
-+    if(src->static_members != &src->default_static_members)
-+    {
-+        if(!(dst->static_members = my_copy_hashtable_ex(NULL,
-+                            src->static_members,
-+                            (ht_copy_fun_t) my_copy_zval_ptr,
-+                            (ht_free_fun_t) my_free_zval_ptr,
-+                            1,
-+                            allocate, deallocate,
-+                            (ht_check_copy_fun_t) my_check_copy_static_member,
-+                            src,
-+                            src->static_members))) {
-+            goto cleanup;
-+        }
-+    }
-+    else
-+    {
-+        dst->static_members = &dst->default_static_members;
-+    }
++/*
++ * apc_cache_clear empties a cache. This can safely be called at any time,
++ * even while other server processes are executing cached source files.
++ */
++extern void apc_cache_clear(T cache);
 +
-+    if(!(my_copy_hashtable(&dst->constants_table,
-+                            &src->constants_table,
-+                            (ht_copy_fun_t) my_copy_zval_ptr,
-+                            (ht_free_fun_t) my_free_zval_ptr,
-+                            1,
-+                            allocate, deallocate))) {
-+        goto cleanup;
-+    }
++/*
++ * apc_cache_insert adds an entry to the cache, using a filename as a key.
++ * Internally, the filename is translated to a canonical representation, so
++ * that relative and absolute filenames will map to a single key. Returns
++ * non-zero if the file was successfully inserted, 0 otherwise. If 0 is
++ * returned, the caller must free the cache entry by calling
++ * apc_cache_free_entry (see below).
++ *
++ * key is the value created by apc_cache_make_file_key for file keys.
++ *
++ * value is a cache entry returned by apc_cache_make_entry (see below).
++ */
++extern int apc_cache_insert(T cache, apc_cache_key_t key,
++                            apc_cache_entry_t* value, apc_context_t* ctxt, time_t t);
 +
-+    if (src->doc_comment) {
-+        if(!(dst->doc_comment =
-+                    apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
-+            goto cleanup;
-+        }
-+    }
-+#endif
-+    
-+    if (src->builtin_functions) {
-+        int i, n;
++extern int apc_cache_user_insert(T cache, apc_cache_key_t key,
++                            apc_cache_entry_t* value, apc_context_t* ctxt, time_t t, int exclusive TSRMLS_DC);
 +
-+        for (n = 0; src->type == ZEND_INTERNAL_CLASS && src->builtin_functions[n].fname != NULL; n++) {}
++extern int *apc_cache_insert_mult(apc_cache_t* cache, apc_cache_key_t* keys,
++                            apc_cache_entry_t** values, apc_context_t *ctxt, time_t t, int num_entries);
 +
-+        if(!(dst->builtin_functions =
-+            (zend_function_entry*)
-+                allocate((n + 1) * sizeof(zend_function_entry)))) {
-+            goto cleanup;
-+        }
++/*
++ * apc_cache_find searches for a cache entry by filename, and returns a
++ * pointer to the entry if found, NULL otherwise.
++ *
++ * key is a value created by apc_cache_make_file_key for file keys.
++ */
++extern apc_cache_entry_t* apc_cache_find(T cache, apc_cache_key_t key, time_t t);
 +
++/*
++ * apc_cache_user_find searches for a cache entry by its hashed identifier,
++ * and returns a pointer to the entry if found, NULL otherwise.
++ *
++ */
++extern apc_cache_entry_t* apc_cache_user_find(T cache, char* strkey, int keylen, time_t t);
 +
-+        for (i = 0; i < n; i++) {
-+            if(!my_copy_function_entry(&dst->builtin_functions[i],
-+                                   &src->builtin_functions[i],
-+                                   allocate, deallocate)) {
-+                int ii;
++/*
++ * apc_cache_delete and apc_cache_user_delete finds an entry in the cache and deletes it.
++ */
++extern int apc_cache_delete(apc_cache_t* cache, char *filename, int filename_len);
++extern int apc_cache_user_delete(apc_cache_t* cache, char *strkey, int keylen);
 +
-+                for(ii=i-1; i>=0; i--) my_destroy_function_entry(&dst->builtin_functions[ii], deallocate);
-+                goto cleanup;
-+            }
-+        }
-+        dst->builtin_functions[n].fname = NULL;
-+    }
++/* apc_cach_fetch_zval takes a zval in the cache and reconstructs a runtime
++ * zval from it.
++ *
++ */
++zval* apc_cache_fetch_zval(zval* dst, const zval* src, apc_context_t* ctxt);
 +
-+#ifdef ZEND_ENGINE_2
-+    if (src->filename) {
-+        if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
-+            goto cleanup;
-+        }
-+    }
-+#endif
-+   
-+    return dst;
++/*
++ * apc_cache_release decrements the reference count associated with a cache
++ * entry. Calling apc_cache_find automatically increments the reference count,
++ * and this function must be called post-execution to return the count to its
++ * original value. Failing to do so will prevent the entry from being
++ * garbage-collected.
++ *
++ * entry is the cache entry whose ref count you want to decrement.
++ */
++extern void apc_cache_release(T cache, apc_cache_entry_t* entry);
 +
++/*
++ * apc_cache_make_file_key creates a key object given a relative or absolute
++ * filename and an optional list of auxillary paths to search. include_path is
++ * searched if the filename cannot be found relative to the current working
++ * directory.
++ *
++ * key points to caller-allocated storage (must not be null).
++ *
++ * filename is the path to the source file.
++ *
++ * include_path is a colon-separated list of directories to search.
++ *
++ * and finally we pass in the current request time so we can avoid
++ * caching files with a current mtime which tends to indicate that
++ * they are still being written to.
++ */
++extern int apc_cache_make_file_key(apc_cache_key_t* key,
++                                   const char* filename,
++                                   const char* include_path,
++                                   time_t t
++                                   TSRMLS_DC);
 +
-+cleanup:
-+    if(dst->name) deallocate(dst->name);
-+#ifdef ZEND_ENGINE_2
-+    if(dst->doc_comment) deallocate(dst->doc_comment);
-+    if(dst->filename) deallocate(dst->filename);
-+#else
-+    if(dst->refcount) deallocate(dst->refcount);
-+#endif
-+    
-+    if(dst->builtin_functions) deallocate(dst->builtin_functions);
-+    if(dst->function_table.arBuckets) my_destroy_hashtable(&dst->function_table, (ht_free_fun_t) my_free_function, deallocate);
-+    if(dst->default_properties.arBuckets) my_destroy_hashtable(&dst->default_properties, (ht_free_fun_t) my_free_zval_ptr, deallocate);
++/*
++ * apc_cache_make_file_entry creates an apc_cache_entry_t object given a filename
++ * and the compilation results returned by the PHP compiler.
++ */
++extern apc_cache_entry_t* apc_cache_make_file_entry(const char* filename,
++                                                    zend_op_array* op_array,
++                                                    apc_function_t* functions,
++                                                    apc_class_t* classes,
++                                                    apc_context_t* ctxt);
 +
-+#ifdef ZEND_ENGINE_2
-+    if(dst->properties_info.arBuckets) my_destroy_hashtable(&dst->properties_info, (ht_free_fun_t) my_free_property_info, deallocate);
-+    if(dst->default_static_members.arBuckets)
-+    {
-+        my_destroy_hashtable(&dst->default_static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
-+    }
-+    if(dst->static_members && dst->static_members != &(dst->default_static_members))
-+    {
-+        my_destroy_hashtable(dst->static_members, (ht_free_fun_t) my_free_zval_ptr, deallocate);
-+        deallocate(dst->static_members);
-+    }
-+    if(dst->constants_table.arBuckets) my_destroy_hashtable(&dst->constants_table, (ht_free_fun_t) my_free_zval_ptr, deallocate);
-+#endif
-+    if(local_dst_alloc) deallocate(dst);
 +
-+    return NULL;
-+}
-+/* }}} */
++zend_bool apc_compile_cache_entry(apc_cache_key_t key, zend_file_handle* h, int type, time_t t, zend_op_array** op_array_pp, apc_cache_entry_t** cache_entry_pp TSRMLS_DC);
 +
-+/* {{{ my_copy_hashtable */
-+static HashTable* my_copy_hashtable_ex(HashTable* dst,
-+                                    HashTable* src,
-+                                    ht_copy_fun_t copy_fn,
-+                                    ht_free_fun_t free_fn,
-+                                    int holds_ptrs,
-+                                    apc_malloc_t allocate, 
-+                                    apc_free_t deallocate,
-+                                    ht_check_copy_fun_t check_fn,
-+                                    ...)
-+{
-+    Bucket* curr = NULL;
-+    Bucket* prev = NULL;
-+    Bucket* newp = NULL;
-+    int first = 1;
-+    int local_dst_alloc = 0;
-+    int index = 0;
++/*
++ * apc_cache_make_user_entry creates an apc_cache_entry_t object given an info string
++ * and the zval to be stored.
++ */
++extern apc_cache_entry_t* apc_cache_make_user_entry(const char* info, int info_len, const zval *val, apc_context_t* ctxt, const unsigned int ttl);
 +
-+    assert(src != NULL);
++extern int apc_cache_make_user_key(apc_cache_key_t* key, char* identifier, int identifier_len, const time_t t);
 +
-+    if (!dst) {
-+        CHECK(dst = (HashTable*) allocate(sizeof(src[0])));
-+        local_dst_alloc = 1;
-+    }
++/* {{{ struct definition: apc_cache_link_data_t */
++typedef union _apc_cache_link_data_t {
++    struct {
++        char *filename;
++        dev_t device;
++        ino_t inode;
++        unsigned char *md5;
++    } file;
++    struct {
++        char *info;
++        unsigned int ttl;
++    } user;
++} apc_cache_link_data_t;
++/* }}} */
 +
-+    memcpy(dst, src, sizeof(src[0]));
++/* {{{ struct definition: apc_cache_link_t */
++typedef struct apc_cache_link_t apc_cache_link_t;
++struct apc_cache_link_t {
++    apc_cache_link_data_t data;
++    unsigned char type;
++    unsigned long num_hits;
++    time_t mtime;
++    time_t creation_time;
++    time_t deletion_time;
++    time_t access_time;
++    int ref_count;
++    size_t mem_size;
++    apc_cache_link_t* next;
++};
++/* }}} */
 +
-+    /* allocate buckets for the new hashtable */
-+    if(!(dst->arBuckets = allocate(dst->nTableSize * sizeof(Bucket*)))) {
-+        if(local_dst_alloc) deallocate(dst);
-+        return NULL;
-+    }
++/* {{{ struct definition: apc_cache_info_t */
++typedef struct apc_cache_info_t apc_cache_info_t;
++struct apc_cache_info_t {
++    int num_slots;
++    unsigned long num_hits;
++    unsigned long num_misses;
++    unsigned long num_inserts;
++    unsigned long expunges;
++    int ttl;
++    apc_cache_link_t* list;
++    apc_cache_link_t* deleted_list;
++    time_t start_time;
++    int num_entries;
++    size_t mem_size;
++};
++/* }}} */
 +
-+    memset(dst->arBuckets, 0, dst->nTableSize * sizeof(Bucket*));
-+    dst->pInternalPointer = NULL;
-+    dst->pListHead = NULL;
-+    
-+    for (curr = src->pListHead; curr != NULL; curr = curr->pListNext) {
-+        int n = curr->h % dst->nTableSize;
++/* {{{ struct definition: slot_t */
++typedef struct slot_t slot_t;
++struct slot_t {
++    apc_cache_key_t key;        /* slot key */
++    apc_cache_entry_t* value;   /* slot value */
++    slot_t* next;               /* next slot in linked list */
++    unsigned long num_hits;     /* number of hits to this bucket */
++    time_t creation_time;       /* time slot was initialized */
++    time_t deletion_time;       /* time slot was removed from cache */
++    time_t access_time;         /* time slot was last accessed */
++};
++/* }}} */
 +
-+        if(check_fn) {
-+            va_list args;
-+            va_start(args, check_fn);
++/* {{{ struct definition: cache_header_t
++   Any values that must be shared among processes should go in here. */
++typedef struct cache_header_t cache_header_t;
++struct cache_header_t {
++    apc_lck_t lock;             /* read/write lock (exclusive blocking cache lock) */
++    apc_lck_t wrlock;           /* write lock (non-blocking used to prevent cache slams) */
++    unsigned long num_hits;     /* total successful hits in cache */
++    unsigned long num_misses;   /* total unsuccessful hits in cache */
++    unsigned long num_inserts;  /* total successful inserts in cache */
++    unsigned long expunges;     /* total number of expunges */
++    slot_t* deleted_list;       /* linked list of to-be-deleted slots */
++    time_t start_time;          /* time the above counters were reset */
++    zend_bool busy;             /* Flag to tell clients when we are busy cleaning the cache */
++    int num_entries;            /* Statistic on the number of entries */
++    size_t mem_size;            /* Statistic on the memory size used by this cache */
++    apc_keyid_t lastkey;        /* the key that is being inserted (user cache) */
++};
++/* }}} */
 +
-+            /* Call the check_fn to see if the current bucket 
-+             * needs to be copied out
-+             */
-+            if(!check_fn(curr, args)) {
-+                dst->nNumOfElements--;
-+                continue;
-+            }
++typedef void (*apc_expunge_cb_t)(T cache, size_t n); 
 +
-+            va_end(args);
-+        }
++/* {{{ struct definition: apc_cache_t */
++struct apc_cache_t {
++    void* shmaddr;                /* process (local) address of shared cache */
++    cache_header_t* header;       /* cache header (stored in SHM) */
++    slot_t** slots;               /* array of cache slots (stored in SHM) */
++    int num_slots;                /* number of slots in cache */
++    int gc_ttl;                   /* maximum time on GC list for a slot */
++    int ttl;                      /* if slot is needed and entry's access time is older than this ttl, remove it */
++    apc_expunge_cb_t expunge_cb;  /* cache specific expunge callback to free up sma memory */
++    uint has_lock;                /* flag for possible recursive locks within the same process */
++};
++/* }}} */
 +
-+        /* create a copy of the bucket 'curr' */
-+        if(!(newp =
-+            (Bucket*) apc_xmemcpy(curr,
-+                                  sizeof(Bucket) + curr->nKeyLength - 1,
-+                                  allocate))) {
-+            goto cleanup;
-+        }
++extern apc_cache_info_t* apc_cache_info(T cache, zend_bool limited);
++extern void apc_cache_free_info(apc_cache_info_t* info);
++extern void apc_cache_unlock(apc_cache_t* cache);
++extern zend_bool apc_cache_busy(apc_cache_t* cache);
++extern zend_bool apc_cache_write_lock(apc_cache_t* cache);
++extern void apc_cache_write_unlock(apc_cache_t* cache);
++extern zend_bool apc_cache_is_last_key(apc_cache_t* cache, apc_cache_key_t* key, time_t t);
 +
-+        /* insert 'newp' into the linked list at its hashed index */
-+        if (dst->arBuckets[n]) {
-+            newp->pNext = dst->arBuckets[n];
-+            newp->pLast = NULL;
-+            newp->pNext->pLast = newp;
-+        }
-+        else {
-+            newp->pNext = newp->pLast = NULL;
-+        }
++/* used by apc_rfc1867 to update data in-place - not to be used elsewhere */
 +
-+        dst->arBuckets[n] = newp;
++typedef int (*apc_cache_updater_t)(apc_cache_t*, apc_cache_entry_t*, void* data);
++extern int _apc_cache_user_update(apc_cache_t* cache, char *strkey, int keylen,
++                                    apc_cache_updater_t updater, void* data TSRMLS_DC);
 +
-+        /* copy the bucket data using our 'copy_fn' callback function */
-+        if(!(newp->pData = copy_fn(NULL, curr->pData, allocate, deallocate))) {
-+            goto cleanup;
-+        }
 +
-+        if (holds_ptrs) {
-+            memcpy(&newp->pDataPtr, newp->pData, sizeof(void*));
-+        }
-+        else {
-+            newp->pDataPtr = NULL;
-+        }
++#undef T
++#endif
 +
-+        /* insert 'newp' into the table-thread linked list */
-+        newp->pListLast = prev;
-+        newp->pListNext = NULL;
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_compile.c php-5.3.1/ext/apc/apc_compile.c
+--- php-5.3.1.orig/ext/apc/apc_compile.c       1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_compile.c    1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,1775 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt.                                 |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          Rasmus Lerdorf <rasmus@php.net>                             |
++  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
++  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
++  +----------------------------------------------------------------------+
 +
-+        if (prev) {
-+            prev->pListNext = newp;
-+        }
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
 +
-+        if (first) {
-+            dst->pListHead = newp;
-+            first = 0;
-+        }
++   All other licensing and usage conditions are those of the PHP Group.
 +
-+        prev = newp;
-+    }
++ */
 +
-+    dst->pListTail = newp;
++/* $Id: apc_compile.c 284580 2009-07-22 06:05:31Z kalle $ */
 +
-+    return dst;
-+    
-+    cleanup:
-+    for(index = 0; index < dst->nTableSize; index++)
-+    {
-+        curr = dst->arBuckets[index];
-+        while(curr != NULL)
-+        {
-+            Bucket * tmp = curr;
-+            if(curr->pData && free_fn)
-+            {
-+                free_fn(curr->pData, deallocate);
-+            }
-+            curr = curr->pNext;
-+            deallocate(tmp);
-+        }
-+    }   
-+    deallocate(dst->arBuckets);
-+    if(local_dst_alloc) deallocate(dst);
-+    else dst->arBuckets = NULL;
++#include "apc_compile.h"
++#include "apc_globals.h"
++#include "apc_zend.h"
++#include "ext/standard/php_var.h"
++#include "ext/standard/php_smart_str.h"
 +
-+    return NULL;
-+}
-+/* }}} */
++#ifndef IS_CONSTANT_TYPE_MASK
++#define IS_CONSTANT_TYPE_MASK (~IS_CONSTANT_INDEX)
++#endif
 +
-+/* {{{ my_copy_static_variables */
-+static HashTable* my_copy_static_variables(zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate)
-+{ 
-+    if (src->static_variables == NULL) {
-+        return NULL;
-+    }
++typedef void* (*ht_copy_fun_t)(void*, void*, apc_context_t*);
++//typedef void  (*ht_free_fun_t)(void*, apc_context_t*);
++typedef int (*ht_check_copy_fun_t)(Bucket*, va_list);
 +
-+    return my_copy_hashtable(NULL,
-+                             src->static_variables,
-+                             (ht_copy_fun_t) my_copy_zval_ptr,
-+                             (ht_free_fun_t) my_free_zval_ptr,
-+                             1,
-+                             allocate, deallocate);
-+}
-+/* }}} */
++typedef void (*ht_fixup_fun_t)(Bucket*, zend_class_entry*, zend_class_entry*);
 +
-+/* {{{ apc_copy_zval */
-+zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate)
-+{
-+    int local_dst_alloc = 0;
-+    assert(src != NULL);
++#define CHECK(p) { if ((p) == NULL) return NULL; }
 +
-+    if (!dst) {
-+        CHECK(dst = (zval*) allocate(sizeof(zval)));
-+        local_dst_alloc = 1;
-+    }
++/* {{{ internal function declarations */
 +
-+    dst = my_copy_zval(dst, src, allocate, deallocate);
-+    if(!dst) {
-+        if(local_dst_alloc) deallocate(dst);
-+        return NULL;
-+    }
-+    return dst; 
-+}
-+/* }}} */
++static zend_function* my_bitwise_copy_function(zend_function*, zend_function*, apc_context_t*);
 +
-+#ifdef ZEND_ENGINE_2
-+/* {{{ apc_fixup_op_array_jumps */
-+static void apc_fixup_op_array_jumps(zend_op_array *dst, zend_op_array *src )
-+{
-+    int i;
++/*
++ * The "copy" functions perform deep-copies on a particular data structure
++ * (passed as the second argument). They also optionally allocate space for
++ * the destination data structure if the first argument is null.
++ */
++static zval** my_copy_zval_ptr(zval**, const zval**, apc_context_t*);
++static zval* my_copy_zval(zval*, const zval*, apc_context_t*);
++static znode* my_copy_znode(znode*, znode*, apc_context_t*);
++static zend_op* my_copy_zend_op(zend_op*, zend_op*, apc_context_t*);
++static zend_function* my_copy_function(zend_function*, zend_function*, apc_context_t*);
++static zend_function_entry* my_copy_function_entry(zend_function_entry*, const zend_function_entry*, apc_context_t*);
++static zend_class_entry* my_copy_class_entry(zend_class_entry*, zend_class_entry*, apc_context_t*);
++static HashTable* my_copy_hashtable_ex(HashTable*, HashTable*, ht_copy_fun_t, int, apc_context_t*, ht_check_copy_fun_t, ...);
++#define my_copy_hashtable( dst, src, copy_fn, holds_ptr, ctxt) \
++    my_copy_hashtable_ex(dst, src, copy_fn, holds_ptr, ctxt, NULL)
++static HashTable* my_copy_static_variables(zend_op_array* src, apc_context_t*);
++static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_context_t*);
++static zend_arg_info* my_copy_arg_info_array(zend_arg_info*, const zend_arg_info*, uint, apc_context_t*);
++static zend_arg_info* my_copy_arg_info(zend_arg_info*, const zend_arg_info*, apc_context_t*);
 +
-+    for (i=0; i < dst->last; ++i) {
-+        zend_op *zo = &(dst->opcodes[i]);
-+        /*convert opline number to jump address*/
-+        switch (zo->opcode) {
-+            case ZEND_JMP:
-+                /*Note: if src->opcodes != dst->opcodes then we need to the opline according to src*/
-+                zo->op1.u.jmp_addr = dst->opcodes + (zo->op1.u.jmp_addr - src->opcodes);
-+                break;
-+            case ZEND_JMPZ:
-+            case ZEND_JMPNZ:
-+            case ZEND_JMPZ_EX:
-+            case ZEND_JMPNZ_EX:
-+                zo->op2.u.jmp_addr = dst->opcodes + (zo->op2.u.jmp_addr - src->opcodes);
-+                break;
-+            default:
-+                break;
++/*
++ * The "fixup" functions need for ZEND_ENGINE_2
++ */
++static void my_fixup_function( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
++static void my_fixup_hashtable( HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst );
++/* my_fixup_function_for_execution is the same as my_fixup_function
++ * but named differently for clarity
++ */
++#define my_fixup_function_for_execution my_fixup_function
++
++#ifdef ZEND_ENGINE_2_2
++static void my_fixup_property_info( Bucket *p, zend_class_entry *src, zend_class_entry *dst );
++#define my_fixup_property_info_for_execution my_fixup_property_info
++#endif
++
++/*
++ * These functions return "1" if the member/function is
++ * defined/overridden in the 'current' class and not inherited.
++ */
++static int my_check_copy_function(Bucket* src, va_list args);
++static int my_check_copy_default_property(Bucket* p, va_list args);
++static int my_check_copy_property_info(Bucket* src, va_list args);
++static int my_check_copy_static_member(Bucket* src, va_list args);
++
++/* }}} */
++
++/* {{{ check_op_array_integrity */
++#if 0
++static void check_op_array_integrity(zend_op_array* src)
++{
++    int i, j;
++
++    /* These sorts of checks really aren't particularly effective, but they
++     * can provide a welcome sanity check when debugging. Just don't enable
++     * for production use!  */
++
++    assert(src->refcount != NULL);
++    assert(src->opcodes != NULL);
++    assert(src->last > 0);
++
++    for (i = 0; i < src->last; i++) {
++        zend_op* op = &src->opcodes[i];
++        znode* nodes[] = { &op->result, &op->op1, &op->op2 };
++        for (j = 0; j < 3; j++) {
++            assert(nodes[j]->op_type == IS_CONST ||
++                   nodes[j]->op_type == IS_VAR ||
++                   nodes[j]->op_type == IS_TMP_VAR ||
++                   nodes[j]->op_type == IS_UNUSED);
++
++            if (nodes[j]->op_type == IS_CONST) {
++                int type = nodes[j]->u.constant.type;
++                assert(type == IS_RESOURCE ||
++                       type == IS_BOOL ||
++                       type == IS_LONG ||
++                       type == IS_DOUBLE ||
++                       type == IS_NULL ||
++                       type == IS_CONSTANT ||
++                       type == IS_STRING ||
++                       type == FLAG_IS_BC ||
++                       type == IS_ARRAY ||
++                       type == IS_CONSTANT_ARRAY ||
++                       type == IS_OBJECT);
++            }
 +        }
 +    }
 +}
-+/* }}} */
 +#endif
++/* }}} */
 +
-+/* {{{ apc_copy_op_array */
-+zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
++/* {{{ my_bitwise_copy_function */
++static zend_function* my_bitwise_copy_function(zend_function* dst, zend_function* src, apc_context_t* ctxt)
 +{
-+    int i;
-+    int local_dst_alloc = 0;
-+    apc_fileinfo_t fileinfo;
-+    char canon_path[MAXPATHLEN];
-+    char *fullpath = NULL;
-+#ifdef ZEND_ENGINE_2
-+    apc_opflags_t * flags = NULL;
-+#endif
++    apc_pool* pool = ctxt->pool;
 +
 +    assert(src != NULL);
 +
 +    if (!dst) {
-+        CHECK(dst = (zend_op_array*) allocate(sizeof(src[0])));
-+        local_dst_alloc = 1;
++        CHECK(dst = (zend_function*) apc_pool_alloc(pool, sizeof(src[0])));
 +    }
 +
-+    if(APCG(apc_optimize_function)) {
-+        APCG(apc_optimize_function)(src TSRMLS_CC);
-+    }
-+    
-+    /* start with a bitwise copy of the array */
++    /* We only need to do a bitwise copy */
 +    memcpy(dst, src, sizeof(src[0]));
 +
-+    dst->function_name = NULL;
-+    dst->filename = NULL;
-+    dst->refcount = NULL;
-+    dst->opcodes = NULL;
-+    dst->brk_cont_array = NULL;
-+    dst->static_variables = NULL;
-+#ifdef ZEND_ENGINE_2
-+    dst->try_catch_array = NULL;
-+    dst->arg_info = NULL;
-+    dst->doc_comment = NULL;
-+#else
-+    dst->arg_types = NULL;
-+#endif
-+#ifdef ZEND_ENGINE_2_1
-+    dst->vars = NULL;
-+#endif
++    return dst;
++}
++/* }}} */
 +
-+    /* copy the arg types array (if set) */
-+#ifdef ZEND_ENGINE_2
-+    if (src->arg_info) {
-+        if(!(dst->arg_info = my_copy_arg_info_array(NULL,
-+                                                src->arg_info,
-+                                                src->num_args,
-+                                                allocate,
-+                                                deallocate))) {
-+            goto cleanup;
-+        }
-+    }
-+#else    
-+    if (src->arg_types) {
-+        if(!(dst->arg_types = apc_xmemcpy(src->arg_types,
-+                        sizeof(src->arg_types[0]) * (src->arg_types[0]+1),
-+                        allocate))) {
-+            goto cleanup;
-+        }
++/* {{{ my_copy_zval_ptr */
++static zval** my_copy_zval_ptr(zval** dst, const zval** src, apc_context_t* ctxt)
++{
++    zval* dst_new;
++    apc_pool* pool = ctxt->pool;
++    int usegc = (ctxt->copy == APC_COPY_OUT_OPCODE) || (ctxt->copy == APC_COPY_OUT_USER);
++
++    assert(src != NULL);
++
++    if (!dst) {
++        CHECK(dst = (zval**) apc_pool_alloc(pool, sizeof(zval*)));
 +    }
-+#endif
 +
-+    if (src->function_name) {
-+        if(!(dst->function_name = apc_xstrdup(src->function_name, allocate))) {
-+            goto cleanup;
-+        }
++    if(usegc) {
++        ALLOC_ZVAL(dst[0]);
++        CHECK(dst[0]);
++    } else {
++        CHECK((dst[0] = (zval*) apc_pool_alloc(pool, sizeof(zval))));
 +    }
-+    if (src->filename) {
-+        if(!(dst->filename = apc_xstrdup(src->filename, allocate))) {
-+            goto cleanup;
++
++    CHECK((dst_new = my_copy_zval(*dst, *src, ctxt)));
++
++    if(dst_new != *dst) {
++        if(usegc) {
++            TSRMLS_FETCH();
++            FREE_ZVAL(dst[0]);
 +        }
++        *dst = dst_new;
 +    }
 +
-+    if(!(dst->refcount = apc_xmemcpy(src->refcount,
-+                                      sizeof(src->refcount[0]),
-+                                      allocate))) {
-+        goto cleanup;
-+    }
++    return dst;
++}
++/* }}} */
 +
-+    /* deep-copy the opcodes */
-+    if(!(dst->opcodes = (zend_op*) allocate(sizeof(zend_op) * src->last))) {
-+        goto cleanup;
++/* {{{ my_serialize_object */
++static zval* my_serialize_object(zval* dst, const zval* src, apc_context_t* ctxt)
++{
++    smart_str buf = {0};
++    php_serialize_data_t var_hash;
++    apc_pool* pool = ctxt->pool;
++
++    TSRMLS_FETCH();
++
++    PHP_VAR_SERIALIZE_INIT(var_hash);
++    php_var_serialize(&buf, (zval**)&src, &var_hash TSRMLS_CC);
++    PHP_VAR_SERIALIZE_DESTROY(var_hash);
++
++    if(buf.c) {
++        dst->type = src->type & ~IS_CONSTANT_INDEX;
++        dst->value.str.len = buf.len;
++        CHECK(dst->value.str.val = apc_pmemcpy(buf.c, buf.len+1, pool));
++        dst->type = src->type;
++        smart_str_free(&buf);
 +    }
 +
-+#ifdef ZEND_ENGINE_2
-+    if(APCG(reserved_offset) != -1) {
-+        /* Insanity alert: the void* pointer is cast into an apc_opflags_t 
-+         * struct. apc_zend_init() checks to ensure that it fits in a void* */
-+        flags = (apc_opflags_t*) & (dst->reserved[APCG(reserved_offset)]);
-+        memset(flags, 0, sizeof(apc_opflags_t));
-+        /* assert(sizeof(apc_opflags_t) < sizeof(dst->reserved)); */
++    return dst;
++}
++/* }}} */
++
++/* {{{ my_unserialize_object */
++static zval* my_unserialize_object(zval* dst, const zval* src, apc_context_t* ctxt)
++{
++    php_unserialize_data_t var_hash;
++    const unsigned char *p = (unsigned char*)Z_STRVAL_P(src);
++
++    TSRMLS_FETCH();
++
++    PHP_VAR_UNSERIALIZE_INIT(var_hash);
++    if(!php_var_unserialize(&dst, &p, p + Z_STRLEN_P(src), &var_hash TSRMLS_CC)) {
++        PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
++        zval_dtor(dst);
++        php_error_docref(NULL TSRMLS_CC, E_NOTICE, "Error at offset %ld of %d bytes", (long)((char*)p - Z_STRVAL_P(src)), Z_STRLEN_P(src));
++        dst->type = IS_NULL;
 +    }
-+#endif
-+    
-+    for (i = 0; i < src->last; i++) {
-+#ifdef ZEND_ENGINE_2
-+        zend_op *zo = &(src->opcodes[i]);
-+        /* a lot of files are merely constant arrays with no jumps */
-+        switch (zo->opcode) {
-+            case ZEND_JMP:
-+            case ZEND_JMPZ:
-+            case ZEND_JMPNZ:
-+            case ZEND_JMPZ_EX:
-+            case ZEND_JMPNZ_EX:
-+                if(flags != NULL) {
-+                    flags->has_jumps = 1;
-+                }
-+                break;
-+#ifdef ZEND_ENGINE_2
-+            /* auto_globals_jit was not in php-4.3.* */
-+            case ZEND_FETCH_R:
-+            case ZEND_FETCH_W:
-+            case ZEND_FETCH_IS:
-+            case ZEND_FETCH_FUNC_ARG:
-+                if(PG(auto_globals_jit) && flags != NULL)
-+                {
-+                     /* The fetch is only required if auto_globals_jit=1  */
-+                    if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&
-+                            zo->op1.op_type == IS_CONST && 
-+                            zo->op1.u.constant.type == IS_STRING) {
-+                        znode * varname = &zo->op1;
-+                        if (varname->u.constant.value.str.val[0] == '_') {
-+#define SET_IF_AUTOGLOBAL(member) \
-+    if(!strcmp(varname->u.constant.value.str.val, #member)) \
-+        flags->member = 1 /* no ';' here */
-+                            SET_IF_AUTOGLOBAL(_GET);
-+                            else SET_IF_AUTOGLOBAL(_POST);
-+                            else SET_IF_AUTOGLOBAL(_COOKIE);
-+                            else SET_IF_AUTOGLOBAL(_SERVER);
-+                            else SET_IF_AUTOGLOBAL(_ENV);
-+                            else SET_IF_AUTOGLOBAL(_FILES);
-+                            else SET_IF_AUTOGLOBAL(_REQUEST);
-+                            else if(zend_is_auto_global(
-+                                            varname->u.constant.value.str.val,
-+                                            varname->u.constant.value.str.len
-+                                            TSRMLS_CC))
-+                            {
-+                                flags->unknown_global = 1;
-+                            }
-+                        }
-+                    }
-+                }
-+                break;
-+#endif
-+            case ZEND_RECV_INIT:
-+                if(zo->op2.op_type == IS_CONST &&
-+                    zo->op2.u.constant.type == IS_CONSTANT_ARRAY) {
-+                    if(flags != NULL) {
-+                        flags->deep_copy = 1;
-+                    }
-+                }
-+                break;
-+            default:
-+                if((zo->op1.op_type == IS_CONST &&
-+                    zo->op1.u.constant.type == IS_CONSTANT_ARRAY) ||
-+                    (zo->op2.op_type == IS_CONST &&
-+                        zo->op2.u.constant.type == IS_CONSTANT_ARRAY)) {
-+                    if(flags != NULL) {
-+                        flags->deep_copy = 1;
-+                    }
-+                }
-+                break;
-+        }
-+#endif
-+        if(!(my_copy_zend_op(dst->opcodes+i, src->opcodes+i, allocate, deallocate))) {
-+            int ii;
-+            for(ii = i-1; ii>=0; ii--) {
-+                my_destroy_zend_op(dst->opcodes+ii, deallocate);
-+            }
-+            goto  cleanup;
-+        }
-+#ifdef ZEND_ENGINE_2
-+/* This code breaks apc's rule#1 - cache what you compile */
-+        if(APCG(fpstat)==0) {
-+            if((zo->opcode == ZEND_INCLUDE_OR_EVAL) && 
-+                (zo->op1.op_type == IS_CONST && zo->op1.u.constant.type == IS_STRING)) {
-+                /* constant includes */
-+                if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(&zo->op1.u.constant),Z_STRLEN_P(&zo->op1.u.constant))) { 
-+                    if (apc_search_paths(Z_STRVAL_P(&zo->op1.u.constant), PG(include_path), &fileinfo) == 0) {
-+                        if((fullpath = realpath(fileinfo.fullpath, canon_path))) {
-+                            /* everything has to go through a realpath() */
-+                            zend_op *dzo = &(dst->opcodes[i]);
-+                            deallocate(dzo->op1.u.constant.value.str.val);
-+                            dzo->op1.u.constant.value.str.len = strlen(fullpath);
-+                            dzo->op1.u.constant.value.str.val = apc_xstrdup(fullpath, allocate);
-+                        }
-+                    }
-+                }
++    PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
++    return dst;
++}
++/* }}} */
++
++/* {{{ my_copy_zval */
++static zval* my_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt)
++{
++    zval **tmp;
++    apc_pool* pool = ctxt->pool;
++    TSRMLS_FETCH();
++
++    assert(dst != NULL);
++    assert(src != NULL);
++
++    memcpy(dst, src, sizeof(src[0]));
++
++    if(APCG(copied_zvals).nTableSize) {
++        if(zend_hash_index_find(&APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
++            if(Z_ISREF_P((zval*)src)) {
++                Z_SET_ISREF_PP(tmp);
 +            }
++            Z_ADDREF_PP(tmp);
++            return *tmp;
 +        }
-+#endif 
++
++        zend_hash_index_update(&APCG(copied_zvals), (ulong)src, (void**)&dst, sizeof(zval*), NULL);
 +    }
 +
-+#ifdef ZEND_ENGINE_2
-+    if(flags == NULL || flags->has_jumps) {
-+        apc_fixup_op_array_jumps(dst,src);
-+    }
-+#endif
-+
-+    /* copy the break-continue array */
-+    if (src->brk_cont_array) {
-+        if(!(dst->brk_cont_array =
-+            apc_xmemcpy(src->brk_cont_array,
-+                        sizeof(src->brk_cont_array[0]) * src->last_brk_cont,
-+                        allocate))) {
-+            goto cleanup_opcodes;
-+        }
-+    }
-+
-+    /* copy the table of static variables */
-+    if (src->static_variables) {
-+        if(!(dst->static_variables = my_copy_static_variables(src, allocate, deallocate))) {
-+            goto cleanup_opcodes;
-+        }
-+    }
-+    
-+#ifdef ZEND_ENGINE_2
-+    if (src->try_catch_array) {
-+        if(!(dst->try_catch_array = 
-+                apc_xmemcpy(src->try_catch_array,
-+                        sizeof(src->try_catch_array[0]) * src->last_try_catch,
-+                        allocate))) {
-+            goto cleanup_opcodes;
-+        }
-+    }
-+#endif
-+
-+#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
-+    if (src->vars) {
-+        if(!(dst->vars = apc_xmemcpy(src->vars,
-+                            sizeof(src->vars[0]) * src->last_var,
-+                            allocate))) {
-+            goto cleanup_opcodes;
-+        }
-+        
-+        for(i = 0; i <  src->last_var; i++) dst->vars[i].name = NULL;
-+        
-+        for(i = 0; i <  src->last_var; i++) {
-+            if(!(dst->vars[i].name = apc_xmemcpy(src->vars[i].name,
-+                                src->vars[i].name_len + 1,
-+                                allocate))) {
-+                dst->last_var = i;
-+                goto cleanup_opcodes;
-+            }
-+        }
-+    }
-+#endif
-+
-+#ifdef ZEND_ENGINE_2
-+    if (src->doc_comment) {
-+        if (!(dst->doc_comment 
-+                = apc_xmemcpy(src->doc_comment, src->doc_comment_len+1, allocate))) {
-+            goto cleanup_opcodes;
-+        }
-+    }
-+#endif
-+
-+    return dst;
-+
-+cleanup_opcodes:
-+    if(dst->opcodes) {
-+        for(i=0; i < src->last; i++) my_destroy_zend_op(dst->opcodes+i, deallocate);
-+    }
-+cleanup:
-+    if(dst->function_name) deallocate(dst->function_name);
-+    if(dst->refcount) deallocate(dst->refcount);
-+    if(dst->filename) deallocate(dst->filename);
-+#ifdef ZEND_ENGINE_2
-+    if(dst->arg_info) my_free_arg_info_array(dst->arg_info, dst->num_args, deallocate);
-+    if(dst->try_catch_array) deallocate(dst->try_catch_array);
-+    if(dst->doc_comment) deallocate(dst->doc_comment);
-+#else
-+    if(dst->arg_types) deallocate(dst->arg_types);
-+#endif
-+    if(dst->opcodes) deallocate(dst->opcodes);
-+    if(dst->brk_cont_array) deallocate(dst->brk_cont_array);
-+    if(dst->static_variables) my_free_hashtable(dst->static_variables, (ht_free_fun_t)my_free_zval_ptr, (apc_free_t)deallocate);
-+#ifdef ZEND_ENGINE_2_1
-+    if (dst->vars) {
-+      for(i=0; i < dst->last_var; i++) {
-+            if(dst->vars[i].name) deallocate(dst->vars[i].name);    
-+        }
-+        deallocate(dst->vars);
-+    }
-+#endif
-+    if(local_dst_alloc) deallocate(dst);
-+    return NULL;
-+}
-+/* }}} */
-+
-+/* {{{ apc_copy_new_functions */
-+apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
-+{
-+    apc_function_t* array;
-+    int new_count;              /* number of new functions in table */
-+    int i;
-+
-+    new_count = zend_hash_num_elements(CG(function_table)) - old_count;
-+    assert(new_count >= 0);
-+
-+    CHECK(array =
-+        (apc_function_t*)
-+            allocate(sizeof(apc_function_t) * (new_count+1)));
-+
-+    if (new_count == 0) {
-+        array[0].function = NULL;
-+        return array;
-+    }
-+    
-+    /* Skip the first `old_count` functions in the table */
-+    zend_hash_internal_pointer_reset(CG(function_table));
-+    for (i = 0; i < old_count; i++) {
-+        zend_hash_move_forward(CG(function_table));
-+    }
-+
-+    /* Add the next `new_count` functions to our array */
-+    for (i = 0; i < new_count; i++) {
-+        char* key;
-+        uint key_size;
-+        zend_function* fun;
-+
-+        zend_hash_get_current_key_ex(CG(function_table),
-+                                     &key,
-+                                     &key_size,
-+                                     NULL,
-+                                     0,
-+                                     NULL);
-+
-+        zend_hash_get_current_data(CG(function_table), (void**) &fun);
-+
-+        if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
-+            int ii;
-+            for(ii=i-1; ii>=0; ii--) {
-+                deallocate(array[ii].name);
-+                my_free_function(array[ii].function, deallocate);
-+            }
-+            deallocate(array);
-+            return NULL;
-+        }
-+        array[i].name_len = (int) key_size-1;
-+        if(!(array[i].function = my_copy_function(NULL, fun, allocate, deallocate))) {
-+            int ii;
-+            deallocate(array[i].name);
-+            for(ii=i-1; ii>=0; ii--) {
-+                deallocate(array[ii].name);
-+                my_free_function(array[ii].function, deallocate);
-+            }
-+            deallocate(array);
-+            return NULL;
-+        }
-+        zend_hash_move_forward(CG(function_table));
-+    }
-+
-+    array[i].function = NULL;
-+    return array;
-+}
-+/* }}} */
-+
-+/* {{{ apc_copy_new_classes */
-+apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC)
-+{
-+    apc_class_t* array;
-+    int new_count;              /* number of new classes in table */
-+    int i;
-+    
-+    new_count = zend_hash_num_elements(CG(class_table)) - old_count;
-+    assert(new_count >= 0);
-+
-+    CHECK(array =
-+        (apc_class_t*)
-+            allocate(sizeof(apc_class_t)*(new_count+1)));
-+    
-+    if (new_count == 0) {
-+        array[0].class_entry = NULL;
-+        return array;
-+    }
-+
-+    /* Skip the first `old_count` classes in the table */
-+    zend_hash_internal_pointer_reset(CG(class_table));
-+    for (i = 0; i < old_count; i++) {
-+        zend_hash_move_forward(CG(class_table));
-+    }
-+
-+    /* Add the next `new_count` classes to our array */
-+    for (i = 0; i < new_count; i++) {
-+        char* key;
-+        uint key_size;
-+        zend_class_entry* elem = NULL;
-+
-+        array[i].class_entry = NULL;
-+
-+        zend_hash_get_current_key_ex(CG(class_table),
-+                                     &key,
-+                                     &key_size,
-+                                     NULL,
-+                                     0,
-+                                     NULL);
-+
-+       zend_hash_get_current_data(CG(class_table), (void**) &elem);
-+  
-+        
-+#ifdef ZEND_ENGINE_2
-+              elem = *((zend_class_entry**)elem);
-+#endif
-+        
-+        if(!(array[i].name = apc_xmemcpy(key, (int) key_size, allocate))) {
-+            int ii;
-+
-+            for(ii=i-1; ii>=0; ii--) {
-+                deallocate(array[ii].name);
-+                my_destroy_class_entry(array[ii].class_entry, deallocate);
-+                deallocate(array[ii].class_entry);
-+            }
-+            deallocate(array);
-+            return NULL;
-+        }
-+        array[i].name_len = (int) key_size-1;
-+        if(!(array[i].class_entry = my_copy_class_entry(NULL, elem, allocate, deallocate))) {
-+            int ii;
-+            
-+            deallocate(array[i].name);
-+            for(ii=i-1; ii>=0; ii--) {
-+                deallocate(array[ii].name);
-+                my_destroy_class_entry(array[ii].class_entry, deallocate);
-+                deallocate(array[ii].class_entry);
-+            }
-+            deallocate(array);
-+            return NULL;
-+        }
-+
-+        /*
-+         * If the class has a pointer to its parent class, save the parent
-+         * name so that we can enable compile-time inheritance when we reload
-+         * the child class; otherwise, set the parent name to null and scan
-+         * the op_array to determine if this class inherits from some base
-+         * class at execution-time.
-+         */
-+
-+        if (elem->parent) {
-+            if(!(array[i].parent_name =
-+                apc_xstrdup(elem->parent->name, allocate))) {
-+                int ii;
-+                 
-+                for(ii=i; ii>=0; ii--) {
-+                    deallocate(array[ii].name);
-+                    my_destroy_class_entry(array[ii].class_entry, deallocate);
-+                    deallocate(array[ii].class_entry);
-+                    if(ii==i) continue;
-+                    if(array[ii].parent_name) deallocate(array[ii].parent_name);
-+                }
-+                deallocate(array);
-+                return NULL;
-+            }
-+            array[i].is_derived = 1;
-+        }
-+        else {
-+            array[i].parent_name = NULL;
-+            array[i].is_derived = is_derived_class(op_array, key, key_size);
-+        }
 +
-+        zend_hash_move_forward(CG(class_table));
-+    }
-+
-+    array[i].class_entry = NULL;
-+    return array;
-+}
-+/* }}} */
-+
-+/* {{{ my_destroy_zval_ptr */
-+static void my_destroy_zval_ptr(zval** src, apc_free_t deallocate)
-+{
-+    assert(src != NULL);
-+    if(my_destroy_zval(src[0], deallocate) == SUCCESS) {
-+        deallocate(src[0]);
++    if(ctxt->copy == APC_COPY_OUT_USER || ctxt->copy == APC_COPY_IN_USER) {
++        /* deep copies are refcount(1), but moved up for recursive 
++         * arrays,  which end up being add_ref'd during its copy. */
++        Z_SET_REFCOUNT_P(dst, 1);
++        Z_UNSET_ISREF_P(dst);
++    } else {
++        /* code uses refcount=2 for consts */
++        Z_SET_REFCOUNT_P(dst, Z_REFCOUNT_P((zval*)src));
++        Z_SET_ISREF_TO_P(dst, Z_ISREF_P((zval*)src));
 +    }
-+}
-+/* }}} */
-+
-+/* {{{ my_destroy_zval */
-+static int my_destroy_zval(zval* src, apc_free_t deallocate)
-+{
-+    zval **tmp;
-+    TSRMLS_FETCH();
 +
-+    switch (src->type & ~IS_CONSTANT_INDEX) {
++    switch (src->type & IS_CONSTANT_TYPE_MASK) {
 +    case IS_RESOURCE:
 +    case IS_BOOL:
 +    case IS_LONG:
@@ -3808,1671 +3513,1504 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_compile.c php-5.2.5/ext/apc/apc_compile.c
 +
 +    case IS_CONSTANT:
 +    case IS_STRING:
-+#ifndef ZEND_ENGINE_2        
-+    case FLAG_IS_BC:
-+#endif        
-+        deallocate(src->value.str.val);
-+        break;
-+    
-+    case IS_ARRAY:
-+    
-+        /* Maintain a list of zvals we've copied to properly handle recursive structures */
-+        if(APCG(copied_zvals)) {
-+            if(zend_hash_index_find(APCG(copied_zvals), (ulong)src, (void**)&tmp) == SUCCESS) {
-+                (*tmp)->refcount--;
-+                return FAILURE;
-+            } 
-+            zend_hash_index_update(APCG(copied_zvals), (ulong)src, (void**)&src, sizeof(zval*), NULL);
++        if (src->value.str.val) {
++            CHECK(dst->value.str.val = apc_pmemcpy(src->value.str.val,
++                                                   src->value.str.len+1,
++                                                   pool));
 +        }
-+        /* fall through */
++        break;
 +
++    case IS_ARRAY:
 +    case IS_CONSTANT_ARRAY:
-+        my_free_hashtable(src->value.ht,
-+                          (ht_free_fun_t) my_free_zval_ptr,
-+                          deallocate);
++
++        CHECK(dst->value.ht =
++            my_copy_hashtable(NULL,
++                              src->value.ht,
++                              (ht_copy_fun_t) my_copy_zval_ptr,
++                              1,
++                              ctxt));
 +        break;
 +
 +    case IS_OBJECT:
-+#ifndef ZEND_ENGINE_2        
-+        my_destroy_class_entry(src->value.obj.ce, deallocate);
-+        deallocate(src->value.obj.ce);
-+        my_free_hashtable(src->value.obj.properties,
-+                          (ht_free_fun_t) my_free_zval_ptr,
-+                          deallocate);
-+#endif        
++    
++        dst->type = IS_NULL;
++        if(ctxt->copy == APC_COPY_IN_USER) {
++            dst = my_serialize_object(dst, src, ctxt);
++        } else if(ctxt->copy == APC_COPY_OUT_USER) {
++            dst = my_unserialize_object(dst, src, ctxt);
++        }
 +        break;
 +
 +    default:
 +        assert(0);
 +    }
 +
-+    return SUCCESS;
++    return dst;
 +}
 +/* }}} */
 +
-+/* {{{ my_destroy_znode */
-+static void my_destroy_znode(znode* src, apc_free_t deallocate)
++/* {{{ my_copy_znode */
++static znode* my_copy_znode(znode* dst, znode* src, apc_context_t* ctxt)
 +{
++    assert(dst != NULL);
++    assert(src != NULL);
++
++    memcpy(dst, src, sizeof(src[0]));
++
++#ifdef IS_CV
++    assert(dst ->op_type == IS_CONST ||
++           dst ->op_type == IS_VAR ||
++           dst ->op_type == IS_CV ||
++           dst ->op_type == IS_TMP_VAR ||
++           dst ->op_type == IS_UNUSED);
++#else
++    assert(dst ->op_type == IS_CONST ||
++           dst ->op_type == IS_VAR ||
++           dst ->op_type == IS_TMP_VAR ||
++           dst ->op_type == IS_UNUSED);
++#endif
++
 +    if (src->op_type == IS_CONST) {
-+        my_destroy_zval(&src->u.constant, deallocate);
++        if(!my_copy_zval(&dst->u.constant, &src->u.constant, ctxt)) {
++            return NULL;
++        }
 +    }
++
++    return dst;
 +}
 +/* }}} */
 +
-+/* {{{ my_destroy_zend_op */
-+static void my_destroy_zend_op(zend_op* src, apc_free_t deallocate)
++/* {{{ my_copy_zend_op */
++static zend_op* my_copy_zend_op(zend_op* dst, zend_op* src, apc_context_t* ctxt)
 +{
-+    my_destroy_znode(&src->result, deallocate);
-+    my_destroy_znode(&src->op1, deallocate);
-+    my_destroy_znode(&src->op2, deallocate);
++    assert(dst != NULL);
++    assert(src != NULL);
++
++    memcpy(dst, src, sizeof(src[0]));
++
++    CHECK(my_copy_znode(&dst->result, &src->result, ctxt));
++    CHECK(my_copy_znode(&dst->op1, &src->op1, ctxt));
++    CHECK(my_copy_znode(&dst->op2, &src->op2, ctxt));
++
++    return dst;
 +}
 +/* }}} */
 +
-+/* {{{ my_destroy_function */
-+static void my_destroy_function(zend_function* src, apc_free_t deallocate)
++/* {{{ my_copy_function */
++static zend_function* my_copy_function(zend_function* dst, zend_function* src, apc_context_t* ctxt)
 +{
++    TSRMLS_FETCH();
++
 +    assert(src != NULL);
 +
++    CHECK(dst = my_bitwise_copy_function(dst, src, ctxt));
++
 +    switch (src->type) {
 +    case ZEND_INTERNAL_FUNCTION:
 +    case ZEND_OVERLOADED_FUNCTION:
++        /* shallow copy because op_array is internal */
++        dst->op_array = src->op_array;
 +        break;
-+        
++
 +    case ZEND_USER_FUNCTION:
 +    case ZEND_EVAL_CODE:
-+        my_destroy_op_array(&src->op_array, deallocate);
++        CHECK(apc_copy_op_array(&dst->op_array,
++                                &src->op_array,
++                                ctxt TSRMLS_CC));
 +        break;
 +
 +    default:
 +        assert(0);
 +    }
-+}
-+/* }}} */
-+
-+/* {{{ my_destroy_function_entry */
-+static void my_destroy_function_entry(zend_function_entry* src, apc_free_t deallocate)
-+{
-+    assert(src != NULL);
++    /*
++     * op_array bitwise copying overwrites what ever you modified
++     * before apc_copy_op_array - which is why this code is outside 
++     * my_bitwise_copy_function.
++     */
 +
-+    deallocate(src->fname);
-+#ifdef ZEND_ENGINE_2    
-+    if (src->arg_info) {
-+            my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
-+    }
-+#else
-+    if (src->func_arg_types) {
-+        deallocate(src->func_arg_types);
-+    }
-+#endif    
-+}
-+/* }}} */
++    /* zend_do_inheritance will re-look this up, because the pointers
++     * in prototype are from a function table of another class. It just
++     * helps if that one is from EG(class_table).
++     */
++    dst->common.prototype = NULL;
 +
-+#ifdef ZEND_ENGINE_2    
-+/* {{{ my_destroy_property_info*/
-+static void my_destroy_property_info(zend_property_info* src, apc_free_t deallocate)
-+{
-+    assert(src != NULL);
++    /* once a method is marked as ZEND_ACC_IMPLEMENTED_ABSTRACT then you
++     * have to carry around a prototype. Thankfully zend_do_inheritance
++     * sets this properly as well
++     */
++    dst->common.fn_flags = src->common.fn_flags & (~ZEND_ACC_IMPLEMENTED_ABSTRACT);
 +
-+    deallocate(src->name);
-+#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
-+    if(src->doc_comment) deallocate(src->doc_comment);
-+#endif
++
++    return dst;
 +}
 +/* }}} */
 +
-+/* {{{ my_destroy_arg_info_array */
-+static void my_destroy_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
++/* {{{ my_copy_function_entry */
++static zend_function_entry* my_copy_function_entry(zend_function_entry* dst, const zend_function_entry* src, apc_context_t* ctxt)
 +{
-+    int i = 0;
-+    
 +    assert(src != NULL);
 +
-+    for(i=0; i < num_args; i++) {
-+        my_destroy_arg_info(&src[i], deallocate);
++    if (!dst) {
++        CHECK(dst = (zend_function_entry*) apc_pool_alloc(ctxt->pool, sizeof(src[0])));
 +    }
-+}
-+/* }}} */
 +
-+/* {{{ my_destroy_arg_info */
-+static void my_destroy_arg_info(zend_arg_info* src, apc_free_t deallocate)
-+{
-+    assert(src != NULL);
++    /* Start with a bitwise copy */
++    memcpy(dst, src, sizeof(src[0]));
++
++    dst->fname = NULL;
++    dst->arg_info = NULL;
++
++    if (src->fname) {
++        CHECK((dst->fname = apc_pstrdup(src->fname, ctxt->pool)));
++    }
++
++    if (src->arg_info) {
++        CHECK((dst->arg_info = my_copy_arg_info_array(NULL,
++                                                src->arg_info,
++                                                src->num_args,
++                                                ctxt)));
++    }
 +
-+    deallocate(src->name);
-+    deallocate(src->class_name);
++    return dst;
 +}
 +/* }}} */
-+#endif    
 +
-+/* {{{ my_destroy_class_entry */
-+static void my_destroy_class_entry(zend_class_entry* src, apc_free_t deallocate)
++/* {{{ my_copy_property_info */
++static zend_property_info* my_copy_property_info(zend_property_info* dst, zend_property_info* src, apc_context_t* ctxt)
 +{
-+    uint i;
++    apc_pool* pool = ctxt->pool;
 +
 +    assert(src != NULL);
 +
-+    deallocate(src->name);
-+#ifndef ZEND_ENGINE_2    
-+    deallocate(src->refcount);
-+#else
-+    if(src->doc_comment) deallocate(src->doc_comment);
-+    if(src->filename) deallocate(src->filename);
-+#endif
++    if (!dst) {
++        CHECK(dst = (zend_property_info*) apc_pool_alloc(pool, sizeof(*src)));
++    }
 +
-+    my_destroy_hashtable(&src->function_table,
-+                         (ht_free_fun_t) my_free_function,
-+                         deallocate);
++    /* Start with a bitwise copy */
++    memcpy(dst, src, sizeof(*src));
 +
-+    my_destroy_hashtable(&src->default_properties,
-+                         (ht_free_fun_t) my_free_zval_ptr,
-+                         deallocate);
++    dst->name = NULL;
++#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
++    dst->doc_comment = NULL;
++#endif
 +
-+#ifdef ZEND_ENGINE_2
-+    my_destroy_hashtable(&src->properties_info, 
-+                            (ht_free_fun_t) my_free_property_info,
-+                            deallocate);
-+    if(src->static_members) 
-+    {
-+        my_destroy_hashtable(src->static_members,
-+                         (ht_free_fun_t) my_free_zval_ptr,
-+                         deallocate);
-+        if(src->static_members != &(src->default_static_members))
-+        {
-+            deallocate(src->static_members);
-+        }
++    if (src->name) {
++        /* private members are stored inside property_info as a mangled
++         * string of the form:
++         *      \0<classname>\0<membername>\0
++         */
++        CHECK((dst->name = apc_pmemcpy(src->name, src->name_length+1, pool)));
 +    }
 +
-+    my_destroy_hashtable(&src->constants_table, 
-+                            (ht_free_fun_t) my_free_zval_ptr,
-+                            deallocate);
++#if defined(ZEND_ENGINE_2) && PHP_MINOR_VERSION > 0
++    if (src->doc_comment) {
++        CHECK((dst->doc_comment = apc_pmemcpy(src->doc_comment, src->doc_comment_len+1, pool)));
++    }
 +#endif
 +
-+    if (src->builtin_functions) {
-+        for (i = 0; src->builtin_functions[i].fname != NULL; i++) {
-+            my_destroy_function_entry(&src->builtin_functions[i], deallocate);
-+        }
-+        deallocate(src->builtin_functions);
-+    }
++    return dst;
 +}
 +/* }}} */
 +
-+/* {{{ my_destroy_hashtable */
-+static void my_destroy_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
++/* {{{ my_copy_property_info_for_execution */
++static zend_property_info* my_copy_property_info_for_execution(zend_property_info* dst, zend_property_info* src, apc_context_t* ctxt)
 +{
-+    int i;
-+
 +    assert(src != NULL);
 +
-+    for (i = 0; i < src->nTableSize; i++) {
-+        Bucket* p = src->arBuckets[i];
-+        while (p != NULL) {
-+            Bucket* q = p;
-+            p = p->pNext;
-+            free_fn(q->pData, deallocate);
-+            deallocate(q);
-+        }
++    if (!dst) {
++        CHECK(dst = (zend_property_info*) apc_pool_alloc(ctxt->pool, (sizeof(*src))));
 +    }
 +
-+    deallocate(src->arBuckets);
++    /* We need only a shallow copy */
++    memcpy(dst, src, sizeof(*src));
++
++    return dst;
 +}
 +/* }}} */
 +
-+/* {{{ my_destroy_op_array */
-+static void my_destroy_op_array(zend_op_array* src, apc_free_t deallocate)
++/* {{{ my_copy_arg_info_array */
++static zend_arg_info* my_copy_arg_info_array(zend_arg_info* dst, const zend_arg_info* src, uint num_args, apc_context_t* ctxt)
 +{
-+    int i;
++    uint i = 0;
 +
-+    assert(src != NULL);
 +
-+#ifdef ZEND_ENGINE_2
-+    if (src->arg_info) {
-+        my_free_arg_info_array(src->arg_info, src->num_args, deallocate);
-+    }
-+#else    
-+    if (src->arg_types) {
-+        deallocate(src->arg_types);
++    if (!dst) {
++        CHECK(dst = (zend_arg_info*) apc_pool_alloc(ctxt->pool, sizeof(*src)*num_args));
 +    }
-+#endif
-+
-+    deallocate(src->function_name);
-+    deallocate(src->filename);
-+    deallocate(src->refcount);
 +
-+    for (i = 0; i < src->last; i++) {
-+        my_destroy_zend_op(src->opcodes + i, deallocate);
-+    }
-+    deallocate(src->opcodes);
++    /* Start with a bitwise copy */
++    memcpy(dst, src, sizeof(*src)*num_args);
 +
-+    if (src->brk_cont_array) {
-+        deallocate(src->brk_cont_array);
++    for(i=0; i < num_args; i++) {
++        CHECK((my_copy_arg_info( &dst[i], &src[i], ctxt)));
 +    }
 +
-+    if (src->static_variables) {
-+        my_free_hashtable(src->static_variables,
-+                          (ht_free_fun_t) my_free_zval_ptr,
-+                          deallocate);
-+    }
-+    
-+#ifdef ZEND_ENGINE_2_1
-+    if (src->vars) {
-+      for(i=0; i < src->last_var; i++) {
-+            if(src->vars[i].name) deallocate(src->vars[i].name);    
-+        }
-+        deallocate(src->vars);
-+    }
-+#endif
-+#ifdef ZEND_ENGINE_2
-+    if(src->try_catch_array) {
-+        deallocate(src->try_catch_array);
-+    }
-+    if (src->doc_comment) {
-+        deallocate(src->doc_comment);
-+    }
-+#endif
++    return dst;
 +}
 +/* }}} */
 +
-+/* {{{ my_free_zval_ptr */
-+static void my_free_zval_ptr(zval** src, apc_free_t deallocate)
++/* {{{ my_copy_arg_info */
++static zend_arg_info* my_copy_arg_info(zend_arg_info* dst, const zend_arg_info* src, apc_context_t* ctxt)
 +{
-+    my_destroy_zval_ptr(src, deallocate);
-+    deallocate(src);
-+}
-+/* }}} */
++    apc_pool* pool = ctxt->pool;
 +
-+#ifdef ZEND_ENGINE_2
-+/* {{{ my_free_property_info */
-+static void my_free_property_info(zend_property_info* src, apc_free_t deallocate)
-+{
-+    my_destroy_property_info(src, deallocate);
-+    deallocate(src);
-+}
-+/* }}} */
++    assert(src != NULL);
 +
-+/* {{{ my_free_arg_info_array */
-+static void my_free_arg_info_array(zend_arg_info* src, uint num_args, apc_free_t deallocate)
-+{
-+    my_destroy_arg_info_array(src, num_args, deallocate);
-+    deallocate(src);
-+}
-+/* }}} */
++    if (!dst) {
++        CHECK(dst = (zend_arg_info*) apc_pool_alloc(pool, sizeof(*src)));
++    }
 +
-+/* {{{ my_free_arg_info */
-+static void my_free_arg_info(zend_arg_info* src, apc_free_t deallocate)
-+{
-+    my_destroy_arg_info(src, deallocate);
-+    deallocate(src);
-+}
-+/* }}} */
-+#endif
++    /* Start with a bitwise copy */
++    memcpy(dst, src, sizeof(*src));
 +
-+/* {{{ my_free_function */
-+static void my_free_function(zend_function* src, apc_free_t deallocate)
-+{
-+    my_destroy_function(src, deallocate);
-+    deallocate(src);
-+}
-+/* }}} */
++    dst->name = NULL;
++    dst->class_name = NULL;
 +
-+/* {{{ my_free_hashtable */
-+static void my_free_hashtable(HashTable* src, ht_free_fun_t free_fn, apc_free_t deallocate)
-+{
-+    my_destroy_hashtable(src, free_fn, deallocate);
-+    deallocate(src);
-+}
-+/* }}} */
++    if (src->name) {
++        CHECK((dst->name = apc_pmemcpy(src->name, src->name_len+1, pool)));
++    }
 +
-+/* {{{ apc_free_op_array */
-+void apc_free_op_array(zend_op_array* src, apc_free_t deallocate)
-+{
-+    if (src != NULL) {
-+        my_destroy_op_array(src, deallocate);
-+        deallocate(src);
++    if (src->class_name) {
++        CHECK((dst->class_name = apc_pmemcpy(src->class_name, src->class_name_len+1, pool)));
 +    }
++
++    return dst;
 +}
 +/* }}} */
 +
-+/* {{{ apc_free_functions */
-+void apc_free_functions(apc_function_t* src, apc_free_t deallocate)
++/* {{{ apc_copy_class_entry */
++zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_context_t* ctxt)
 +{
-+    int i;
-+
-+    if (src != NULL) {
-+        for (i = 0; src[i].function != NULL; i++) {
-+            deallocate(src[i].name);
-+            my_destroy_function(src[i].function, deallocate);
-+            deallocate(src[i].function);
-+        }   
-+        deallocate(src);
-+    }   
++    return my_copy_class_entry(dst, src, ctxt);
 +}
-+/* }}} */
 +
-+/* {{{ apc_free_classes */
-+void apc_free_classes(apc_class_t* src, apc_free_t deallocate)
++/* {{{ my_copy_class_entry */
++static zend_class_entry* my_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_context_t* ctxt)
 +{
-+    int i;
++    uint i = 0;
++    apc_pool* pool = ctxt->pool;
 +
-+    if (src != NULL) {
-+        for (i = 0; src[i].class_entry != NULL; i++) {
-+            deallocate(src[i].name);
-+            deallocate(src[i].parent_name);
-+            my_destroy_class_entry(src[i].class_entry, deallocate);
-+            deallocate(src[i].class_entry);
-+        }   
-+        deallocate(src);
-+    }   
-+}
-+/* }}} */
++    assert(src != NULL);
 +
-+/* {{{ apc_free_zval */
-+void apc_free_zval(zval* src, apc_free_t deallocate)
-+{
-+    if (src != NULL) {
-+        if(my_destroy_zval(src, deallocate) == SUCCESS) {
-+            deallocate(src);
-+        }
++    if (!dst) {
++        CHECK(dst = (zend_class_entry*) apc_pool_alloc(pool, sizeof(*src)));
 +    }
-+}
-+/* }}} */
 +
++    /* Start with a bitwise copy */
++    memcpy(dst, src, sizeof(*src));
 +
-+/* Used only by my_prepare_op_array_for_execution */
-+#define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION()                                                \
-+                         /* The fetch is only required if auto_globals_jit=1  */                \
-+                        if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&                            \
-+                            zo->op1.op_type == IS_CONST &&                                      \
-+                            zo->op1.u.constant.type == IS_STRING &&                             \
-+                            zo->op1.u.constant.value.str.val[0] == '_') {                       \
-+                                                                                                \
-+                            znode* varname = &zo->op1;                                          \
-+                            (void)zend_is_auto_global(varname->u.constant.value.str.val,        \
-+                                                          varname->u.constant.value.str.len     \
-+                                                          TSRMLS_CC);                           \
-+                        }                                                                       \
++    dst->name = NULL;
++    dst->builtin_functions = NULL;
++    memset(&dst->function_table, 0, sizeof(dst->function_table));
++    memset(&dst->default_properties, 0, sizeof(dst->default_properties));
++    dst->static_members = NULL;
++    dst->doc_comment = NULL;
++    dst->filename = NULL;
++    memset(&dst->properties_info, 0, sizeof(dst->properties_info));
++    memset(&dst->constants_table, 0, sizeof(dst->constants_table));
++    memset(&dst->default_static_members, 0, sizeof(dst->default_static_members));
 +
-+/* {{{ my_prepare_op_array_for_execution */
-+static int my_prepare_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC) 
-+{
-+    /* combine my_fetch_global_vars and my_copy_data_exceptions.
-+     *   - Pre-fetch superglobals which would've been pre-fetched in parse phase.
-+     *   - If the opcode stream contain mutable data, ensure a copy.
-+     *   - Fixup array jumps in the same loop.
-+     */
-+    int i=src->last;
-+    zend_op *zo;
-+    zend_op *dzo;
-+#ifdef ZEND_ENGINE_2
-+    apc_opflags_t * flags = APCG(reserved_offset) != -1 ? 
-+                                (apc_opflags_t*) & (src->reserved[APCG(reserved_offset)]) : NULL;
-+    int needcopy = flags ? flags->deep_copy : 1;
-+    /* auto_globals_jit was not in php4 */
-+    int do_prepare_fetch_global = PG(auto_globals_jit) && (flags == NULL || flags->unknown_global);
++    if (src->name) {
++        CHECK((dst->name = apc_pstrdup(src->name, pool)));
++    }
 +
-+#define FETCH_AUTOGLOBAL(member) do { \
-+    if(flags && flags->member == 1) { \
-+        zend_is_auto_global(#member,\
-+                            (sizeof(#member) - 1)\
-+                            TSRMLS_CC);\
-+    } \
-+}while(0); 
-+            
-+    FETCH_AUTOGLOBAL(_GET);
-+    FETCH_AUTOGLOBAL(_POST);
-+    FETCH_AUTOGLOBAL(_COOKIE);
-+    FETCH_AUTOGLOBAL(_SERVER);
-+    FETCH_AUTOGLOBAL(_ENV);
-+    FETCH_AUTOGLOBAL(_FILES);
-+    FETCH_AUTOGLOBAL(_REQUEST);
++    if(!(my_copy_hashtable_ex(&dst->function_table,
++                            &src->function_table,
++                            (ht_copy_fun_t) my_copy_function,
++                            0,
++                            ctxt,
++                            (ht_check_copy_fun_t) my_check_copy_function,
++                            src))) {
++        return NULL;
++    }
 +
-+#else
-+    int needcopy = 0;
-+    int do_prepare_fetch_global = 0;
-+    int j = 0;
++    /* the interfaces are populated at runtime using ADD_INTERFACE */
++    dst->interfaces = NULL; 
 +
-+    for(j = 0; j < src->last; j++) {
-+        zo = &src->opcodes[j];
-+        
-+        if( ((zo->op1.op_type == IS_CONST &&
-+              zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||  
-+            ((zo->op2.op_type == IS_CONST &&
-+              zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
-+            needcopy = 1;
++    /* the current count includes inherited interfaces as well,
++       the real dynamic ones are the first <n> which are zero'd
++       out in zend_do_end_class_declaration */
++    for(i = 0 ; i < src->num_interfaces ; i++) {
++        if(src->interfaces[i])
++        {
++            dst->num_interfaces = i;
++            break;
 +        }
 +    }
++
++    /* these will either be set inside my_fixup_hashtable or 
++     * they will be copied out from parent inside zend_do_inheritance 
++     */
++    dst->parent = NULL;
++    dst->constructor =  NULL;
++    dst->destructor = NULL;
++    dst->clone = NULL;
++    dst->__get = NULL;
++    dst->__set = NULL;
++    dst->__unset = NULL;
++    dst->__isset = NULL;
++    dst->__call = NULL;
++#ifdef ZEND_ENGINE_2_2
++    dst->__tostring = NULL;
++#endif
++#ifdef ZEND_ENGINE_2_3
++      dst->__callstatic = NULL;
 +#endif
-+    
-+    if(needcopy) {
 +
-+        dst->opcodes = (zend_op*) apc_xmemcpy(src->opcodes, 
-+                                    sizeof(zend_op) * src->last,
-+                                    apc_php_malloc);
-+        zo = src->opcodes;
-+        dzo = dst->opcodes;
-+        while(i > 0) {
++    /* unset function proxies */
++    dst->serialize_func = NULL;
++    dst->unserialize_func = NULL;
 +
-+            if( ((zo->op1.op_type == IS_CONST &&
-+                  zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||  
-+                ((zo->op2.op_type == IS_CONST &&
-+                  zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
++    my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function, src, dst);
 +
-+                if(!(my_copy_zend_op(dzo, zo, apc_php_malloc, apc_php_free))) {
-+                    assert(0); /* emalloc failed or a bad constant array */
-+                }
-+            }
-+            
-+#ifdef ZEND_ENGINE_2
-+            switch(zo->opcode) {
-+                case ZEND_JMP:
-+                    dzo->op1.u.jmp_addr = dst->opcodes + 
-+                                            (zo->op1.u.jmp_addr - src->opcodes);
-+                    break;
-+                case ZEND_JMPZ:
-+                case ZEND_JMPNZ:
-+                case ZEND_JMPZ_EX:
-+                case ZEND_JMPNZ_EX:
-+                    dzo->op2.u.jmp_addr = dst->opcodes + 
-+                                            (zo->op2.u.jmp_addr - src->opcodes);
-+                    break;
-+                case ZEND_FETCH_R:
-+                case ZEND_FETCH_W:
-+                case ZEND_FETCH_IS:
-+                case ZEND_FETCH_FUNC_ARG:
-+                    if(do_prepare_fetch_global)
-+                    {
-+                        APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
-+                    }
-+                    break;
-+                default:
-+                    break;
-+            }
-+#endif
-+            i--;
-+            zo++;
-+            dzo++;
-+        }
-+#ifdef ZEND_ENGINE_2
-+    } else {  /* !needcopy */
-+        /* The fetch is only required if auto_globals_jit=1  */
-+        if(do_prepare_fetch_global)
-+        {
-+            zo = src->opcodes;
-+            while(i > 0) {
++    CHECK((my_copy_hashtable_ex(&dst->default_properties,
++                            &src->default_properties,
++                            (ht_copy_fun_t) my_copy_zval_ptr,
++                            1,
++                            ctxt,
++                            (ht_check_copy_fun_t) my_check_copy_default_property,
++                            src)));
 +
-+                if(zo->opcode == ZEND_FETCH_R || 
-+                   zo->opcode == ZEND_FETCH_W ||
-+                   zo->opcode == ZEND_FETCH_IS ||
-+                   zo->opcode == ZEND_FETCH_FUNC_ARG 
-+                  ) {
-+                    APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
-+                }
++    CHECK((my_copy_hashtable_ex(&dst->properties_info,
++                            &src->properties_info,
++                            (ht_copy_fun_t) my_copy_property_info,
++                            0,
++                            ctxt,
++                            (ht_check_copy_fun_t) my_check_copy_property_info,
++                            src)));
 +
-+                i--;
-+                zo++;
-+            }
-+        }
++#ifdef ZEND_ENGINE_2_2
++    /* php5.2 introduced a scope attribute for property info */
++    my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
 +#endif
++
++    CHECK(my_copy_hashtable_ex(&dst->default_static_members,
++                            &src->default_static_members,
++                            (ht_copy_fun_t) my_copy_zval_ptr,
++                            1,
++                            ctxt,
++                            (ht_check_copy_fun_t) my_check_copy_static_member,
++                            src,
++                            &src->default_static_members));
++
++    if(src->static_members != &src->default_static_members)
++    {
++        CHECK((dst->static_members = my_copy_hashtable_ex(NULL,
++                            src->static_members,
++                            (ht_copy_fun_t) my_copy_zval_ptr,
++                            1,
++                            ctxt,
++                            (ht_check_copy_fun_t) my_check_copy_static_member,
++                            src,
++                            src->static_members)));
++    }
++    else
++    {
++        dst->static_members = &dst->default_static_members;
 +    }
-+    return 1;
-+}
-+/* }}} */
 +
-+/* {{{ apc_copy_op_array_for_execution */
-+zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC)
-+{
-+    if(dst == NULL) {
-+        dst = (zend_op_array*) emalloc(sizeof(src[0]));
++    CHECK((my_copy_hashtable(&dst->constants_table,
++                            &src->constants_table,
++                            (ht_copy_fun_t) my_copy_zval_ptr,
++                            1,
++                            ctxt)));
++
++    if (src->doc_comment) {
++        CHECK(dst->doc_comment =
++                    apc_pmemcpy(src->doc_comment, src->doc_comment_len+1, pool));
 +    }
-+    memcpy(dst, src, sizeof(src[0]));
-+    dst->static_variables = my_copy_static_variables(src, apc_php_malloc, apc_php_free);
 +
-+    dst->refcount = apc_xmemcpy(src->refcount,
-+                                      sizeof(src->refcount[0]),
-+                                      apc_php_malloc);
-+    
-+    my_prepare_op_array_for_execution(dst,src TSRMLS_CC);
++    if (src->builtin_functions) {
++        int i, n;
 +
-+    return dst;
-+}
-+/* }}} */
++        for (n = 0; src->type == ZEND_INTERNAL_CLASS && src->builtin_functions[n].fname != NULL; n++) {}
 +
-+/* {{{ apc_copy_function_for_execution */
-+zend_function* apc_copy_function_for_execution(zend_function* src)
-+{
-+    zend_function* dst;
-+    TSRMLS_FETCH();
++        CHECK((dst->builtin_functions =
++                (zend_function_entry*) apc_pool_alloc(pool, (n + 1) * sizeof(zend_function_entry))));
++
++        for (i = 0; i < n; i++) {
++            CHECK(my_copy_function_entry((zend_function_entry*)(&dst->builtin_functions[i]),
++                                   &src->builtin_functions[i],
++                                   ctxt));
++        }
++        *(char**)&(dst->builtin_functions[n].fname) = NULL;
++    }
++
++    if (src->filename) {
++        CHECK((dst->filename = apc_pstrdup(src->filename, pool)));
++    }
 +
-+    dst = (zend_function*) emalloc(sizeof(src[0]));
-+    memcpy(dst, src, sizeof(src[0]));
-+    apc_copy_op_array_for_execution(&(dst->op_array), &(src->op_array) TSRMLS_CC);
 +    return dst;
 +}
 +/* }}} */
 +
-+/* {{{ apc_copy_function_for_execution_ex */
-+zend_function* apc_copy_function_for_execution_ex(void *dummy, zend_function* src, apc_malloc_t allocate, apc_free_t deallocate)
++/* {{{ my_copy_hashtable */
++static HashTable* my_copy_hashtable_ex(HashTable* dst,
++                                    HashTable* src,
++                                    ht_copy_fun_t copy_fn,
++                                    int holds_ptrs,
++                                    apc_context_t* ctxt,
++                                    ht_check_copy_fun_t check_fn,
++                                    ...)
 +{
-+    if(src->type==ZEND_INTERNAL_FUNCTION || src->type==ZEND_OVERLOADED_FUNCTION) return src;
-+    return apc_copy_function_for_execution(src);
-+}
-+/* }}} */
++    Bucket* curr = NULL;
++    Bucket* prev = NULL;
++    Bucket* newp = NULL;
++    int first = 1;
++    apc_pool* pool = ctxt->pool;
 +
-+/* {{{ apc_copy_class_entry_for_execution */
-+zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived)
-+{
-+    zend_class_entry* dst = (zend_class_entry*) emalloc(sizeof(src[0]));
-+    memcpy(dst, src, sizeof(src[0]));
++    assert(src != NULL);
 +
-+#ifdef ZEND_ENGINE_2
-+    if(src->num_interfaces)
-+    {
-+        /* These are slots to be populated later by ADD_INTERFACE insns */
-+        dst->interfaces = apc_php_malloc(
-+                            sizeof(zend_class_entry*) * src->num_interfaces);
-+        memset(dst->interfaces, 0, 
-+                            sizeof(zend_class_entry*) * src->num_interfaces);
-+    }
-+    else
-+    {
-+        /* assert(dst->interfaces == NULL); */
++    if (!dst) {
++        CHECK(dst = (HashTable*) apc_pool_alloc(pool, sizeof(src[0])));
 +    }
-+#endif
 +
-+#ifndef ZEND_ENGINE_2    
-+    dst->refcount = apc_xmemcpy(src->refcount,
-+                                      sizeof(src->refcount[0]),
-+                                      apc_php_malloc);
-+#endif        
++    memcpy(dst, src, sizeof(src[0]));
 +
-+    /* Deep-copy the class properties, because they will be modified */
++    /* allocate buckets for the new hashtable */
++    CHECK((dst->arBuckets = apc_pool_alloc(pool, dst->nTableSize * sizeof(Bucket*))));
 +
-+    my_copy_hashtable(&dst->default_properties,
-+                      &src->default_properties,
-+                      (ht_copy_fun_t) my_copy_zval_ptr,
-+                      (ht_free_fun_t) my_free_zval_ptr,
-+                      1,
-+                      apc_php_malloc, apc_php_free);
++    memset(dst->arBuckets, 0, dst->nTableSize * sizeof(Bucket*));
++    dst->pInternalPointer = NULL;
++    dst->pListHead = NULL;
 +
-+    /* For derived classes, we must also copy the function hashtable (although
-+     * we can merely bitwise copy the functions it contains) */
++    for (curr = src->pListHead; curr != NULL; curr = curr->pListNext) {
++        int n = curr->h % dst->nTableSize;
 +
-+    my_copy_hashtable(&dst->function_table,
-+                      &src->function_table,
-+                      (ht_copy_fun_t) apc_copy_function_for_execution_ex,
-+                      NULL,
-+                      0,
-+                      apc_php_malloc, apc_php_free);
-+#ifdef ZEND_ENGINE_2
-+    my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function_for_execution, src, dst);
++        if(check_fn) {
++            va_list args;
++            va_start(args, check_fn);
 +
-+    /* zend_do_inheritance merges properties_info.
-+     * Need only shallow copying as it doesn't hold the pointers.
-+     */
-+    my_copy_hashtable(&dst->properties_info,
-+                      &src->properties_info,
-+                      (ht_copy_fun_t) my_copy_property_info_for_execution,
-+                      NULL,
-+                      0,
-+                      apc_php_malloc, apc_php_free);
++            /* Call the check_fn to see if the current bucket
++             * needs to be copied out
++             */
++            if(!check_fn(curr, args)) {
++                dst->nNumOfElements--;
++                continue;
++            }
 +
-+#ifdef ZEND_ENGINE_2_2
-+    /* php5.2 introduced a scope attribute for property info */
-+    my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
-+#endif
++            va_end(args);
++        }
 +
-+    /* if inheritance results in a hash_del, it might result in
-+     * a pefree() of the pointers here. Deep copying required. 
-+     */
++        /* create a copy of the bucket 'curr' */
++        CHECK((newp = (Bucket*) apc_pmemcpy(curr,
++                                  sizeof(Bucket) + curr->nKeyLength - 1,
++                                  pool)));
 +
-+    my_copy_hashtable(&dst->constants_table,
-+                      &src->constants_table,
-+                      (ht_copy_fun_t) my_copy_zval_ptr,
-+                      NULL,
-+                      1,
-+                      apc_php_malloc, apc_php_free);
++        /* insert 'newp' into the linked list at its hashed index */
++        if (dst->arBuckets[n]) {
++            newp->pNext = dst->arBuckets[n];
++            newp->pLast = NULL;
++            newp->pNext->pLast = newp;
++        }
++        else {
++            newp->pNext = newp->pLast = NULL;
++        }
 +
-+    my_copy_hashtable(&dst->default_static_members,
-+                      &src->default_static_members,
-+                      (ht_copy_fun_t) my_copy_zval_ptr,
-+                      (ht_free_fun_t) my_free_zval_ptr,
-+                      1,
-+                      apc_php_malloc, apc_php_free);
++        dst->arBuckets[n] = newp;
 +
-+    if(src->static_members != &(src->default_static_members))
-+    {
-+        dst->static_members = my_copy_hashtable(NULL,
-+                          src->static_members,
-+                          (ht_copy_fun_t) my_copy_zval_ptr,
-+                          (ht_free_fun_t) my_free_zval_ptr,
-+                          1,
-+                          apc_php_malloc, apc_php_free);
-+    }
-+    else 
-+    {
-+        dst->static_members = &(dst->default_static_members);
++        /* copy the bucket data using our 'copy_fn' callback function */
++        CHECK((newp->pData = copy_fn(NULL, curr->pData, ctxt)));
++
++        if (holds_ptrs) {
++            memcpy(&newp->pDataPtr, newp->pData, sizeof(void*));
++        }
++        else {
++            newp->pDataPtr = NULL;
++        }
++
++        /* insert 'newp' into the table-thread linked list */
++        newp->pListLast = prev;
++        newp->pListNext = NULL;
++
++        if (prev) {
++            prev->pListNext = newp;
++        }
++
++        if (first) {
++            dst->pListHead = newp;
++            first = 0;
++        }
++
++        prev = newp;
 +    }
 +
-+#endif
++    dst->pListTail = newp;
 +
 +    return dst;
 +}
 +/* }}} */
 +
-+/* {{{ apc_free_class_entry_after_execution */
-+void apc_free_class_entry_after_execution(zend_class_entry* src)
++/* {{{ my_copy_static_variables */
++static HashTable* my_copy_static_variables(zend_op_array* src, apc_context_t* ctxt)
 +{
-+#ifdef ZEND_ENGINE_2
-+    if(src->num_interfaces > 0 && src->interfaces) {
-+        apc_php_free(src->interfaces);
-+        src->interfaces = NULL;
-+        src->num_interfaces = 0;
-+    }
-+    /* my_destroy_hashtable() does not play nice with refcounts */
-+
-+    zend_hash_clean(&src->default_static_members);
-+    if(src->static_members != &(src->default_static_members))
-+    {
-+        zend_hash_destroy(src->static_members);
-+        apc_php_free(src->static_members);
-+        src->static_members = NULL;
-+    }
-+    else
-+    {
-+        src->static_members = NULL;
++    if (src->static_variables == NULL) {
++        return NULL;
 +    }
-+    zend_hash_clean(&src->default_properties);
-+    zend_hash_clean(&src->constants_table);
-+#endif
 +
-+    /* TODO: more cleanup */
++    return my_copy_hashtable(NULL,
++                             src->static_variables,
++                             (ht_copy_fun_t) my_copy_zval_ptr,
++                             1,
++                             ctxt);
 +}
 +/* }}} */
 +
-+#ifdef ZEND_ENGINE_2
-+
-+/* {{{ my_fixup_function */
-+static void my_fixup_function(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
++/* {{{ apc_copy_zval */
++zval* apc_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt)
 +{
-+    zend_function* zf = p->pData;
++    apc_pool* pool = ctxt->pool;
++    int usegc = (ctxt->copy == APC_COPY_OUT_OPCODE) || (ctxt->copy == APC_COPY_OUT_USER);
 +
-+    #define SET_IF_SAME_NAME(member) \
-+    do { \
-+        if(src->member && !strcmp(zf->common.function_name, src->member->common.function_name)) { \
-+            dst->member = zf; \
-+        } \
-+    } \
-+    while(0)
++    assert(src != NULL);
 +
-+    if(zf->common.scope == src)
-+    {
-+    
-+        /* Fixing up the default functions for objects here since
-+         * we need to compare with the newly allocated functions
-+         *
-+         * caveat: a sub-class method can have the same name as the
-+         * parent's constructor and create problems.
-+         */
-+        
-+        if(zf->common.fn_flags & ZEND_ACC_CTOR) dst->constructor = zf;
-+        else if(zf->common.fn_flags & ZEND_ACC_DTOR) dst->destructor = zf;
-+        else if(zf->common.fn_flags & ZEND_ACC_CLONE) dst->clone = zf;
-+        else
-+        {
-+            SET_IF_SAME_NAME(__get);
-+            SET_IF_SAME_NAME(__set);
-+            SET_IF_SAME_NAME(__unset);
-+            SET_IF_SAME_NAME(__isset);
-+            SET_IF_SAME_NAME(__call);
-+#ifdef ZEND_ENGINE_2_2
-+            SET_IF_SAME_NAME(__tostring);
-+#endif
++    if (!dst) {
++        if(usegc) {
++            ALLOC_ZVAL(dst);
++            CHECK(dst);
++        } else {
++            CHECK(dst = (zval*) apc_pool_alloc(pool, sizeof(zval)));
 +        }
-+        zf->common.scope = dst;
-+    }
-+    else
-+    {
-+        /* no other function should reach here */
-+        assert(0);
 +    }
 +
-+    #undef SET_IF_SAME_NAME
-+}
-+/* }}} */
-+
-+#ifdef ZEND_ENGINE_2_2
-+/* {{{ my_fixup_property_info */
-+static void my_fixup_property_info(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
-+{
-+    zend_property_info* property_info = (zend_property_info*)p->pData;
-+
-+    if(property_info->ce == src)
-+    {
-+        property_info->ce = dst;
-+    }
-+    else
-+    {
-+        assert(0); /* should never happen */
-+    }
++    CHECK(dst = my_copy_zval(dst, src, ctxt));
++    return dst;
 +}
 +/* }}} */
-+#endif
 +
-+/* {{{ my_fixup_hashtable */
-+static void my_fixup_hashtable(HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst)
++/* {{{ apc_fixup_op_array_jumps */
++static void apc_fixup_op_array_jumps(zend_op_array *dst, zend_op_array *src )
 +{
-+    Bucket *p;
-+    
-+      uint i;
-+    
-+      for (i = 0; i < ht->nTableSize; i++) {
-+              if(!ht->arBuckets) break;
-+        p = ht->arBuckets[i];
-+              while (p != NULL) {
-+            fixup(p, src, dst);
-+                      p = p->pNext;
-+              }
-+      }
-+}
-+/* }}} */
-+
-+#endif
++    uint i;
 +
-+/* {{{ my_check_copy_function */
-+static int my_check_copy_function(Bucket* p, va_list args)
-+{
-+    zend_class_entry* src = va_arg(args, zend_class_entry*);
-+    zend_function* zf = (zend_function*)p->pData;
-+#ifndef ZEND_ENGINE_2
-+    zend_class_entry* parent = src->parent;
-+    zend_function* parent_fn = NULL;
++    for (i=0; i < dst->last; ++i) {
++        zend_op *zo = &(dst->opcodes[i]);
++        /*convert opline number to jump address*/
++        switch (zo->opcode) {
++            case ZEND_JMP:
++                /*Note: if src->opcodes != dst->opcodes then we need to the opline according to src*/
++                zo->op1.u.jmp_addr = dst->opcodes + (zo->op1.u.jmp_addr - src->opcodes);
++                break;
++            case ZEND_JMPZ:
++            case ZEND_JMPNZ:
++            case ZEND_JMPZ_EX:
++            case ZEND_JMPNZ_EX:
++#ifdef ZEND_ENGINE_2_3
++            case ZEND_JMP_SET:
 +#endif
-+
-+#ifdef ZEND_ENGINE_2
-+    return (zf->common.scope == src);
-+#else
-+      if (parent &&
-+        zend_hash_quick_find(&parent->function_table, p->arKey, 
-+            p->nKeyLength, p->h, (void **) &parent_fn)==SUCCESS) {
-+        
-+        if((parent_fn && zf) && 
-+                (parent_fn->op_array.refcount == zf->op_array.refcount))
-+        {
-+            return 0;
++                zo->op2.u.jmp_addr = dst->opcodes + (zo->op2.u.jmp_addr - src->opcodes);
++                break;
++            default:
++                break;
 +        }
 +    }
-+    return 1;
-+#endif 
 +}
 +/* }}} */
 +
-+/* {{{ my_check_copy_default_property */
-+static int my_check_copy_default_property(Bucket* p, va_list args)
++/* {{{ apc_copy_op_array */
++zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC)
 +{
-+    zend_class_entry* src = va_arg(args, zend_class_entry*);
-+    zend_class_entry* parent = src->parent;
-+    zval ** child_prop = (zval**)p->pData;
-+    zval ** parent_prop = NULL;
++    int i;
++    apc_fileinfo_t fileinfo;
++    char canon_path[MAXPATHLEN];
++    char *fullpath = NULL;
++    apc_opflags_t * flags = NULL;
++    apc_pool* pool = ctxt->pool;
 +
-+      if (parent &&
-+        zend_hash_quick_find(&parent->default_properties, p->arKey, 
-+            p->nKeyLength, p->h, (void **) &parent_prop)==SUCCESS) {
++    assert(src != NULL);
 +
-+        if((parent_prop && child_prop) && (*parent_prop) == (*child_prop))
-+        {
-+            return 0;
-+        }
++    if (!dst) {
++        CHECK(dst = (zend_op_array*) apc_pool_alloc(pool, sizeof(src[0])));
 +    }
-+    
-+    /* possibly not in the parent */
-+    return 1;
-+}
-+/* }}} */
 +
-+#ifdef ZEND_ENGINE_2
++    if(APCG(apc_optimize_function)) {
++        APCG(apc_optimize_function)(src TSRMLS_CC);
++    }
 +
-+/* {{{ my_check_copy_property_info */
-+static int my_check_copy_property_info(Bucket* p, va_list args)
-+{
-+    zend_class_entry* src = va_arg(args, zend_class_entry*);
-+    zend_class_entry* parent = src->parent;
-+    zend_property_info* child_info = (zend_property_info*)p->pData;
-+    zend_property_info* parent_info = NULL;
++    /* start with a bitwise copy of the array */
++    memcpy(dst, src, sizeof(src[0]));
 +
-+#ifdef ZEND_ENGINE_2_2
-+    /* so much easier */
-+    return (child_info->ce == src);
++    dst->function_name = NULL;
++    dst->filename = NULL;
++    dst->refcount = NULL;
++    dst->opcodes = NULL;
++    dst->brk_cont_array = NULL;
++    dst->static_variables = NULL;
++    dst->try_catch_array = NULL;
++    dst->arg_info = NULL;
++    dst->doc_comment = NULL;
++#ifdef ZEND_ENGINE_2_1
++    dst->vars = NULL;
 +#endif
 +
-+      if (parent &&
-+        zend_hash_quick_find(&parent->properties_info, p->arKey, p->nKeyLength, 
-+            p->h, (void **) &parent_info)==SUCCESS) {
-+        if(parent_info->flags & ZEND_ACC_PRIVATE)
-+        {
-+            return 1;
-+        }
-+        if((parent_info->flags & ZEND_ACC_PPP_MASK) != 
-+            (child_info->flags & ZEND_ACC_PPP_MASK))
-+        {
-+            /* TODO: figure out whether ACC_CHANGED is more appropriate
-+             * here */
-+            return 1;
-+        }
-+        return 0;
++    /* copy the arg types array (if set) */
++    if (src->arg_info) {
++        CHECK(dst->arg_info = my_copy_arg_info_array(NULL,
++                                                src->arg_info,
++                                                src->num_args,
++                                                ctxt));
 +    }
-+    
-+    /* property doesn't exist in parent, copy into cached child */
-+    return 1;
-+}
-+/* }}} */
 +
-+/* {{{ my_check_copy_static_member */
-+static int my_check_copy_static_member(Bucket* p, va_list args)
-+{
-+    zend_class_entry* src = va_arg(args, zend_class_entry*);
-+    HashTable * ht = va_arg(args, HashTable*);
-+    zend_class_entry* parent = src->parent;
-+    HashTable * parent_ht = NULL;
-+    char * member_name;
-+    char * class_name = NULL;
++    if (src->function_name) {
++        CHECK(dst->function_name = apc_pstrdup(src->function_name, pool));
++    }
++    if (src->filename) {
++        CHECK(dst->filename = apc_pstrdup(src->filename, pool));
++    }
 +
-+    zend_property_info *parent_info = NULL;
-+    zend_property_info *child_info = NULL;
-+    zval ** parent_prop = NULL;
-+    zval ** child_prop = (zval**)(p->pData);
++    CHECK(dst->refcount = apc_pmemcpy(src->refcount,
++                                      sizeof(src->refcount[0]),
++                                      pool));
 +
-+    if(!parent) {
-+        return 1;
++    /* deep-copy the opcodes */
++    CHECK(dst->opcodes = (zend_op*) apc_pool_alloc(pool, sizeof(zend_op) * src->last));
++
++    if(apc_reserved_offset != -1) {
++        /* Insanity alert: the void* pointer is cast into an apc_opflags_t 
++         * struct. apc_zend_init() checks to ensure that it fits in a void* */
++        flags = (apc_opflags_t*) & (dst->reserved[apc_reserved_offset]);
++        memset(flags, 0, sizeof(apc_opflags_t));
++        /* assert(sizeof(apc_opflags_t) < sizeof(dst->reserved)); */
 +    }
 +
-+    /* these do not need free'ing */
-+#ifdef ZEND_ENGINE_2_2
-+    zend_unmangle_property_name(p->arKey, p->nKeyLength-1, &class_name, &member_name);
-+#else
-+    zend_unmangle_property_name(p->arKey, &class_name, &member_name);
++    for (i = 0; (uint) i < src->last; i++) {
++        zend_op *zo = &(src->opcodes[i]);
++        /* a lot of files are merely constant arrays with no jumps */
++        switch (zo->opcode) {
++            case ZEND_JMP:
++            case ZEND_JMPZ:
++            case ZEND_JMPNZ:
++            case ZEND_JMPZ_EX:
++            case ZEND_JMPNZ_EX:
++#ifdef ZEND_ENGINE_2_3
++            case ZEND_JMP_SET:
 +#endif
-+
-+    /* please refer do_inherit_property_access_check in zend_compile.c
-+     * to understand why we lookup in properties_info.
-+     */
-+    if((zend_hash_find(&parent->properties_info, member_name, 
-+                        strlen(member_name)+1, (void**)&parent_info) == SUCCESS)
-+        &&
-+        (zend_hash_find(&src->properties_info, member_name,
-+                        strlen(member_name)+1, (void**)&child_info) == SUCCESS))
-+    {
-+        if(child_info->flags & ZEND_ACC_STATIC &&    
-+            (parent_info->flags & ZEND_ACC_PROTECTED &&
-+            child_info->flags & ZEND_ACC_PUBLIC))
-+        {
-+            /* Do not copy into static_members. zend_do_inheritance
-+             * will automatically insert a NULL value.
-+             * TODO: decrement refcount or fixup when copying out for exec ? 
-+             */ 
-+            return 0;
-+        }
-+        if(ht == &(src->default_static_members))
-+        {
-+            parent_ht = &parent->default_static_members;
++                if(flags != NULL) {
++                    flags->has_jumps = 1;
++                }
++                break;
++            /* auto_globals_jit was not in php-4.3.* */
++            case ZEND_FETCH_R:
++            case ZEND_FETCH_W:
++            case ZEND_FETCH_IS:
++            case ZEND_FETCH_FUNC_ARG:
++                if(PG(auto_globals_jit) && flags != NULL)
++                {
++                     /* The fetch is only required if auto_globals_jit=1  */
++                    if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&
++                            zo->op1.op_type == IS_CONST && 
++                            zo->op1.u.constant.type == IS_STRING) {
++                        znode * varname = &zo->op1;
++                        if (varname->u.constant.value.str.val[0] == '_') {
++#define SET_IF_AUTOGLOBAL(member) \
++    if(!strcmp(varname->u.constant.value.str.val, #member)) \
++        flags->member = 1 /* no ';' here */
++                            SET_IF_AUTOGLOBAL(_GET);
++                            else SET_IF_AUTOGLOBAL(_POST);
++                            else SET_IF_AUTOGLOBAL(_COOKIE);
++                            else SET_IF_AUTOGLOBAL(_SERVER);
++                            else SET_IF_AUTOGLOBAL(_ENV);
++                            else SET_IF_AUTOGLOBAL(_FILES);
++                            else SET_IF_AUTOGLOBAL(_REQUEST);
++                            else if(zend_is_auto_global(
++                                            varname->u.constant.value.str.val,
++                                            varname->u.constant.value.str.len
++                                            TSRMLS_CC))
++                            {
++                                flags->unknown_global = 1;
++                            }
++                        }
++                    }
++                }
++                break;
++            case ZEND_RECV_INIT:
++                if(zo->op2.op_type == IS_CONST &&
++                    zo->op2.u.constant.type == IS_CONSTANT_ARRAY) {
++                    if(flags != NULL) {
++                        flags->deep_copy = 1;
++                    }
++                }
++                break;
++            default:
++                if((zo->op1.op_type == IS_CONST &&
++                    zo->op1.u.constant.type == IS_CONSTANT_ARRAY) ||
++                    (zo->op2.op_type == IS_CONST &&
++                        zo->op2.u.constant.type == IS_CONSTANT_ARRAY)) {
++                    if(flags != NULL) {
++                        flags->deep_copy = 1;
++                    }
++                }
++                break;
 +        }
-+        else
-+        {
-+            parent_ht = parent->static_members;
++
++        if(!(my_copy_zend_op(dst->opcodes+i, src->opcodes+i, ctxt))) {
++            return NULL;
 +        }
 +
-+        if(zend_hash_quick_find(parent_ht, p->arKey,
-+                       p->nKeyLength, p->h, (void**)&parent_prop) == SUCCESS)
-+        {
-+            /* they point to the same zval */
-+            if(*parent_prop == *child_prop)
-+            {
-+                return 0;
++/* This code breaks apc's rule#1 - cache what you compile */
++        if((APCG(fpstat)==0) && APCG(canonicalize)) {
++            if((zo->opcode == ZEND_INCLUDE_OR_EVAL) && 
++                (zo->op1.op_type == IS_CONST && zo->op1.u.constant.type == IS_STRING)) {
++                /* constant includes */
++                if(!IS_ABSOLUTE_PATH(Z_STRVAL_P(&zo->op1.u.constant),Z_STRLEN_P(&zo->op1.u.constant))) { 
++                    if (apc_search_paths(Z_STRVAL_P(&zo->op1.u.constant), PG(include_path), &fileinfo) == 0) {
++                        if((fullpath = realpath(fileinfo.fullpath, canon_path))) {
++                            /* everything has to go through a realpath() */
++                            zend_op *dzo = &(dst->opcodes[i]);
++                            dzo->op1.u.constant.value.str.len = strlen(fullpath);
++                            dzo->op1.u.constant.value.str.val = apc_pstrdup(fullpath, pool);
++                        }
++                    }
++                }
 +            }
 +        }
 +    }
-+    
-+    return 1;
-+}
-+/* }}} */
-+#endif
-+
-+/* {{{ apc_register_optimizer(apc_optimize_function_t optimizer)
-+ *      register a optimizer callback function, returns the previous callback
-+ */
-+apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC) {
-+    apc_optimize_function_t old_optimizer = APCG(apc_optimize_function);
-+    APCG(apc_optimize_function) = optimizer;
-+    return old_optimizer;
-+}
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_compile.h php-5.2.5/ext/apc/apc_compile.h
---- php-5.2.5-orig/ext/apc/apc_compile.h       1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_compile.h    2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,134 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
-+  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
-+  +----------------------------------------------------------------------+
++    if(flags == NULL || flags->has_jumps) {
++        apc_fixup_op_array_jumps(dst,src);
++    }
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++    /* copy the break-continue array */
++    if (src->brk_cont_array) {
++        CHECK(dst->brk_cont_array = apc_pmemcpy(src->brk_cont_array,
++                                    sizeof(src->brk_cont_array[0]) * src->last_brk_cont,
++                                    pool));
++    }
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++    /* copy the table of static variables */
++    if (src->static_variables) {
++        CHECK(dst->static_variables = my_copy_static_variables(src, ctxt));
++    }
 +
-+ */
++    if (src->try_catch_array) {
++        CHECK(dst->try_catch_array = apc_pmemcpy(src->try_catch_array,
++                                        sizeof(src->try_catch_array[0]) * src->last_try_catch,
++                                        pool));
++    }
 +
-+/* $Id: apc_compile.h,v 3.19 2007/03/08 22:03:35 gopalv Exp $ */
++#ifdef ZEND_ENGINE_2_1 /* PHP 5.1 */
++    if (src->vars) {
++        CHECK(dst->vars = apc_pmemcpy(src->vars,
++                            sizeof(src->vars[0]) * src->last_var,
++                            pool));
 +
-+#ifndef APC_COMPILE_H
-+#define APC_COMPILE_H
++        for(i = 0; i <  src->last_var; i++) dst->vars[i].name = NULL;
 +
-+/*
-+ * This module encapsulates most of the complexity involved in deep-copying
-+ * the Zend compiler data structures. The routines are allocator-agnostic, so
-+ * the same function can be used for copying to and from shared memory.
-+ */
++        for(i = 0; i <  src->last_var; i++) {
++            CHECK(dst->vars[i].name = apc_pmemcpy(src->vars[i].name,
++                                src->vars[i].name_len + 1,
++                                pool));
++        }
++    }
++#endif
 +
-+#include "apc.h"
-+#include "apc_php.h"
++    if (src->doc_comment) {
++        CHECK(dst->doc_comment
++                = apc_pmemcpy(src->doc_comment, src->doc_comment_len+1, pool));
++    }
 +
-+/* {{{ struct definition: apc_function_t */
-+typedef struct apc_function_t apc_function_t;
-+struct apc_function_t {
-+    char* name;                 /* the function name */
-+    int name_len;               /* length of name */
-+    zend_function* function;    /* the zend function data structure */
-+};
++    return dst;
++}
 +/* }}} */
 +
-+/* {{{ struct definition: apc_class_t */
-+typedef struct apc_class_t apc_class_t;
-+struct apc_class_t {
-+    char* name;                     /* the class name */
-+    int name_len;                   /* length of name */
-+    int is_derived;                 /* true if this is a derived class */
-+    char* parent_name;              /* the parent class name */
-+    zend_class_entry* class_entry;  /* the zend class data structure */
-+};
-+/* }}} */
 +
-+/* {{{ struct definition: apc_opflags_t */
-+typedef struct apc_opflags_t apc_opflags_t;
-+struct apc_opflags_t {
-+    unsigned int has_jumps      : 1; /* has jump offsets */
-+    unsigned int deep_copy      : 1; /* needs deep copy */
++/* {{{ apc_copy_new_functions */
++apc_function_t* apc_copy_new_functions(int old_count, apc_context_t* ctxt TSRMLS_DC)
++{
++    apc_function_t* array;
++    int new_count;              /* number of new functions in table */
++    int i;
++    apc_pool* pool = ctxt->pool;
 +
-+    /* autoglobal bits */
-+    unsigned int _POST          : 1;
-+    unsigned int _GET           : 1;
-+    unsigned int _COOKIE        : 1;
-+    unsigned int _SERVER        : 1;
-+    unsigned int _ENV           : 1;
-+    unsigned int _FILES         : 1;
-+    unsigned int _REQUEST       : 1;
-+    unsigned int unknown_global : 1;
-+};
-+/* }}} */
++    new_count = zend_hash_num_elements(CG(function_table)) - old_count;
++    assert(new_count >= 0);
 +
-+/*
-+ * These are the top-level copy functions.
-+ */
++    CHECK(array =
++        (apc_function_t*)
++            apc_pool_alloc(pool, sizeof(apc_function_t) * (new_count+1)));
 +
-+extern zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
-+extern zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_malloc_t allocate, apc_free_t deallocate);
-+extern apc_function_t* apc_copy_new_functions(int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
-+extern apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_malloc_t allocate, apc_free_t deallocate TSRMLS_DC);
-+extern zval* apc_copy_zval(zval* dst, const zval* src, apc_malloc_t allocate, apc_free_t deallocate);
++    if (new_count == 0) {
++        array[0].function = NULL;
++        return array;
++    }
 +
-+/*
-+ * Deallocation functions corresponding to the copy functions above.
-+ */
++    /* Skip the first `old_count` functions in the table */
++    zend_hash_internal_pointer_reset(CG(function_table));
++    for (i = 0; i < old_count; i++) {
++        zend_hash_move_forward(CG(function_table));
++    }
 +
-+extern void apc_free_op_array(zend_op_array* src, apc_free_t deallocate);
-+extern void apc_free_functions(apc_function_t* src, apc_free_t deallocate);
-+extern void apc_free_classes(apc_class_t* src, apc_free_t deallocate);
-+extern void apc_free_zval(zval* src, apc_free_t deallocate);
++    /* Add the next `new_count` functions to our array */
++    for (i = 0; i < new_count; i++) {
++        char* key;
++        uint key_size;
++        zend_function* fun;
 +
-+/*
-+ * These "copy-for-execution" functions must be called after retrieving an
-+ * object from the shared cache. They do the minimal amount of work necessary
-+ * to allow multiple processes to concurrently execute the same VM data
-+ * structures.
-+ */
++        zend_hash_get_current_key_ex(CG(function_table),
++                                     &key,
++                                     &key_size,
++                                     NULL,
++                                     0,
++                                     NULL);
 +
-+extern zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src TSRMLS_DC);
-+extern zend_function* apc_copy_function_for_execution(zend_function* src);
-+extern zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, int is_derived);
++        zend_hash_get_current_data(CG(function_table), (void**) &fun);
 +
-+/*
-+ * The "free-after-execution" function performs a cursory clean up of the class data
-+ * This is required to minimize memory leak warnings and to ensure correct destructor
-+ * ordering of some variables.
-+ */
-+extern void apc_free_class_entry_after_execution(zend_class_entry* src);
-+
-+/*
-+ * Optimization callback definition and registration function. 
-+ */
-+typedef zend_op_array* (*apc_optimize_function_t) (zend_op_array* TSRMLS_DC);
-+extern apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC);
++        CHECK(array[i].name = apc_pmemcpy(key, (int) key_size, pool));
++        array[i].name_len = (int) key_size-1;
++        CHECK(array[i].function = my_copy_function(NULL, fun, ctxt));
++        zend_hash_move_forward(CG(function_table));
++    }
 +
-+#endif
++    array[i].function = NULL;
++    return array;
++}
++/* }}} */
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_debug.c php-5.2.5/ext/apc/apc_debug.c
---- php-5.2.5-orig/ext/apc/apc_debug.c 1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_debug.c      2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,57 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
-+  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
-+  +----------------------------------------------------------------------+
++/* {{{ apc_copy_new_classes */
++apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_context_t *ctxt TSRMLS_DC)
++{
++    apc_class_t* array;
++    int new_count;              /* number of new classes in table */
++    int i;
++    apc_pool* pool = ctxt->pool;
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++    new_count = zend_hash_num_elements(CG(class_table)) - old_count;
++    assert(new_count >= 0);
 +
-+   All other licensing and usage conditions are those of the PHP Group.
-+*/
++    CHECK(array =
++        (apc_class_t*)
++            apc_pool_alloc(pool, sizeof(apc_class_t)*(new_count+1)));
 +
-+/* $Id: apc_debug.c,v 3.6 2006/12/07 23:51:28 gopalv Exp $ */
-+#include "apc.h"
-+#include <stdio.h>
-+#include "zend_compile.h"
++    if (new_count == 0) {
++        array[0].class_entry = NULL;
++        return array;
++    }
 +
-+#ifdef __DEBUG_APC__
++    /* Skip the first `old_count` classes in the table */
++    zend_hash_internal_pointer_reset(CG(class_table));
++    for (i = 0; i < old_count; i++) {
++        zend_hash_move_forward(CG(class_table));
++    }
 +
-+#include <dlfcn.h>
++    /* Add the next `new_count` classes to our array */
++    for (i = 0; i < new_count; i++) {
++        char* key;
++        uint key_size;
++        zend_class_entry* elem = NULL;
 +
-+/* keep track of vld_dump_oparray() signature */
-+typedef void (*vld_dump_f) (zend_op_array * TSRMLS_DC);
++        array[i].class_entry = NULL;
 +
-+#endif
++        zend_hash_get_current_key_ex(CG(class_table),
++                                     &key,
++                                     &key_size,
++                                     NULL,
++                                     0,
++                                     NULL);
 +
-+void dump(zend_op_array *op_array TSRMLS_DC)
-+{
-+#ifdef __DEBUG_APC__
-+      vld_dump_f dump_op_array = dlsym(NULL, "vld_dump_oparray");
++        zend_hash_get_current_data(CG(class_table), (void**) &elem);
 +
-+      if(dump_op_array)
-+      {
-+              dump_op_array(op_array TSRMLS_CC); 
-+      }
-+      else
-+      {
-+              apc_wprint("vld is not installed or something even worse.");
-+      }
-+#endif
-+}
-diff -ubrN php-5.2.5-orig/ext/apc/apc_debug.h php-5.2.5/ext/apc/apc_debug.h
---- php-5.2.5-orig/ext/apc/apc_debug.h 1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_debug.h      2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1 @@
-+void dump(zend_op_array * TSRMLS_DC);
-diff -ubrN php-5.2.5-orig/ext/apc/apc.dsp php-5.2.5/ext/apc/apc.dsp
---- php-5.2.5-orig/ext/apc/apc.dsp     1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc.dsp  2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,207 @@
-+# Microsoft Developer Studio Project File - Name="apc" - Package Owner=<4>
-+# Microsoft Developer Studio Generated Build File, Format Version 6.00
-+# ** DO NOT EDIT **
 +
-+# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
++        elem = *((zend_class_entry**)elem);
 +
-+CFG=apc - Win32 Debug_TS
-+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
-+!MESSAGE use the Export Makefile command and run
-+!MESSAGE 
-+!MESSAGE NMAKE /f "apc.mak".
-+!MESSAGE 
-+!MESSAGE You can specify a configuration when running NMAKE
-+!MESSAGE by defining the macro CFG on the command line. For example:
-+!MESSAGE 
-+!MESSAGE NMAKE /f "apc.mak" CFG="apc - Win32 Debug_TS"
-+!MESSAGE 
-+!MESSAGE Possible choices for configuration are:
-+!MESSAGE 
-+!MESSAGE "apc - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
-+!MESSAGE "apc - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
-+!MESSAGE 
++        CHECK(array[i].name = apc_pmemcpy(key, (int) key_size, pool));
++        array[i].name_len = (int) key_size-1;
++        CHECK(array[i].class_entry = my_copy_class_entry(NULL, elem, ctxt));
 +
-+# Begin Project
-+# PROP AllowPerConfigDependencies 0
-+# PROP Scc_ProjName ""
-+# PROP Scc_LocalPath ""
-+CPP=cl.exe
-+MTL=midl.exe
-+RSC=rc.exe
++        /*
++         * If the class has a pointer to its parent class, save the parent
++         * name so that we can enable compile-time inheritance when we reload
++         * the child class; otherwise, set the parent name to null and scan
++         * the op_array to determine if this class inherits from some base
++         * class at execution-time.
++         */
 +
-+!IF  "$(CFG)" == "apc - Win32 Debug_TS"
++        if (elem->parent) {
++            CHECK(array[i].parent_name = apc_pstrdup(elem->parent->name, pool));
++        }
++        else {
++            array[i].parent_name = NULL;
++        }
 +
-+# PROP BASE Use_MFC 0
-+# PROP BASE Use_Debug_Libraries 1
-+# PROP BASE Output_Dir "Debug_TS"
-+# PROP BASE Intermediate_Dir "Debug_TS"
-+# PROP BASE Target_Dir ""
-+# PROP Use_MFC 0
-+# PROP Use_Debug_Libraries 1
-+# PROP Output_Dir "Debug_TS"
-+# PROP Intermediate_Dir "Debug_TS"
-+# PROP Ignore_Export_Lib 0
-+# PROP Target_Dir ""
-+# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /GZ /c
-+# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\win32" /I "..\..\..\php4\regex" /D "TSRM_LOCKS" /D HAVE_APC=1 /D "COMPILE_DL_APC" /D ZEND_DEBUG=1 /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /GZ /c
-+# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-+# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
-+# ADD BASE RSC /l 0x409 /d "_DEBUG"
-+# ADD RSC /l 0x409 /d "_DEBUG"
-+BSC32=bscmake.exe
-+# ADD BASE BSC32 /nologo
-+# ADD BSC32 /nologo
-+LINK32=link.exe
-+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-+# ADD LINK32 php4ts_debug.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"Debug_TS/php_apc.dll" /pdbtype:sept /libpath:"..\..\..\php4\Debug_TS"
++        zend_hash_move_forward(CG(class_table));
++    }
 +
-+!ELSEIF  "$(CFG)" == "apc - Win32 Release_TS"
++    array[i].class_entry = NULL;
++    return array;
++}
++/* }}} */
 +
-+# PROP BASE Use_MFC 0
-+# PROP BASE Use_Debug_Libraries 0
-+# PROP BASE Output_Dir "Release_TS"
-+# PROP BASE Intermediate_Dir "Release_TS"
-+# PROP BASE Target_Dir ""
-+# PROP Use_MFC 0
-+# PROP Use_Debug_Libraries 0
-+# PROP Output_Dir "Release_TS"
-+# PROP Intermediate_Dir "Release_TS"
-+# PROP Ignore_Export_Lib 0
-+# PROP Target_Dir ""
-+# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /c
-+# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\win32" /I "..\..\..\php4\regex" /D "TSRM_LOCKS" /D HAVE_APC=1 /D "COMPILE_DL_APC" /D ZEND_DEBUG=0 /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /c
-+# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-+# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
-+# ADD BASE RSC /l 0x409 /d "NDEBUG"
-+# ADD RSC /l 0x409 /d "NDEBUG"
-+BSC32=bscmake.exe
-+# ADD BASE BSC32 /nologo
-+# ADD BSC32 /nologo
-+LINK32=link.exe
-+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-+# ADD LINK32 php4ts.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../../Release_TS/php_apc.dll" /libpath:"..\..\..\php4\Release_TS" /libpath:"..\..\..\php4\Release_TS_Inline"
++/* Used only by my_prepare_op_array_for_execution */
++#define APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION()                                                \
++                         /* The fetch is only required if auto_globals_jit=1  */                \
++                        if(zo->op2.u.EA.type == ZEND_FETCH_GLOBAL &&                            \
++                            zo->op1.op_type == IS_CONST &&                                      \
++                            zo->op1.u.constant.type == IS_STRING &&                             \
++                            zo->op1.u.constant.value.str.val[0] == '_') {                       \
++                                                                                                \
++                            znode* varname = &zo->op1;                                          \
++                            (void)zend_is_auto_global(varname->u.constant.value.str.val,        \
++                                                          varname->u.constant.value.str.len     \
++                                                          TSRMLS_CC);                           \
++                        }                                                                       \
 +
-+!ENDIF 
++/* {{{ my_prepare_op_array_for_execution */
++static int my_prepare_op_array_for_execution(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC) 
++{
++    /* combine my_fetch_global_vars and my_copy_data_exceptions.
++     *   - Pre-fetch superglobals which would've been pre-fetched in parse phase.
++     *   - If the opcode stream contain mutable data, ensure a copy.
++     *   - Fixup array jumps in the same loop.
++     */
++    int i=src->last;
++    zend_op *zo;
++    zend_op *dzo;
++    apc_opflags_t * flags = apc_reserved_offset  != -1 ? 
++                                (apc_opflags_t*) & (src->reserved[apc_reserved_offset]) : NULL;
++    int needcopy = flags ? flags->deep_copy : 1;
++    /* auto_globals_jit was not in php4 */
++    int do_prepare_fetch_global = PG(auto_globals_jit) && (flags == NULL || flags->unknown_global);
 +
-+# Begin Target
++#define FETCH_AUTOGLOBAL(member) do { \
++    if(flags && flags->member == 1) { \
++        zend_is_auto_global(#member,\
++                            (sizeof(#member) - 1)\
++                            TSRMLS_CC);\
++    } \
++} while(0);
 +
-+# Name "apc - Win32 Debug_TS"
-+# Name "apc - Win32 Release_TS"
-+# Begin Group "Source Files"
++    FETCH_AUTOGLOBAL(_GET);
++    FETCH_AUTOGLOBAL(_POST);
++    FETCH_AUTOGLOBAL(_COOKIE);
++    FETCH_AUTOGLOBAL(_SERVER);
++    FETCH_AUTOGLOBAL(_ENV);
++    FETCH_AUTOGLOBAL(_FILES);
++    FETCH_AUTOGLOBAL(_REQUEST);
 +
-+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
-+# Begin Source File
++    if(needcopy) {
 +
-+SOURCE=.\apc.c
-+# End Source File
-+# Begin Source File
++        dst->opcodes = (zend_op*) apc_xmemcpy(src->opcodes,
++                                    sizeof(zend_op) * src->last,
++                                    apc_php_malloc);
++        zo = src->opcodes;
++        dzo = dst->opcodes;
++        while(i > 0) {
 +
-+SOURCE=.\apc_cache.c
-+# End Source File
-+# Begin Source File
++            if( ((zo->op1.op_type == IS_CONST &&
++                  zo->op1.u.constant.type == IS_CONSTANT_ARRAY)) ||
++                ((zo->op2.op_type == IS_CONST &&
++                  zo->op2.u.constant.type == IS_CONSTANT_ARRAY))) {
 +
-+SOURCE=.\apc_compile.c
-+# End Source File
-+# Begin Source File
-+
-+SOURCE=.\apc_debug.c
-+# End Source File
-+# Begin Source File
-+
-+SOURCE=.\apc_fcntl_win32.c
-+# End Source File
-+# Begin Source File
-+
-+SOURCE=.\apc_main.c
-+# End Source File
-+# Begin Source File
-+
-+SOURCE=.\apc_rfc1867.c
-+# End Source File
-+# Begin Source File
-+
-+SOURCE=.\apc_shm.c
-+# End Source File
-+# Begin Source File
++                if(!(my_copy_zend_op(dzo, zo, ctxt))) {
++                    assert(0); /* emalloc failed or a bad constant array */
++                }
++            }
 +
-+SOURCE=.\apc_sma.c
-+# End Source File
-+# Begin Source File
++            switch(zo->opcode) {
++                case ZEND_JMP:
++                    dzo->op1.u.jmp_addr = dst->opcodes +
++                                            (zo->op1.u.jmp_addr - src->opcodes);
++                    break;
++                case ZEND_JMPZ:
++                case ZEND_JMPNZ:
++                case ZEND_JMPZ_EX:
++                case ZEND_JMPNZ_EX:
++#ifdef ZEND_ENGINE_2_3
++                case ZEND_JMP_SET:
++#endif
++                    dzo->op2.u.jmp_addr = dst->opcodes +
++                                            (zo->op2.u.jmp_addr - src->opcodes);
++                    break;
++                case ZEND_FETCH_R:
++                case ZEND_FETCH_W:
++                case ZEND_FETCH_IS:
++                case ZEND_FETCH_FUNC_ARG:
++                    if(do_prepare_fetch_global)
++                    {
++                        APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
++                    }
++                    break;
++                default:
++                    break;
++            }
++            i--;
++            zo++;
++            dzo++;
++        }
++    } else {  /* !needcopy */
++        /* The fetch is only required if auto_globals_jit=1  */
++        if(do_prepare_fetch_global)
++        {
++            zo = src->opcodes;
++            while(i > 0) {
 +
-+SOURCE=.\apc_stack.c
-+# End Source File
-+# Begin Source File
++                if(zo->opcode == ZEND_FETCH_R ||
++                   zo->opcode == ZEND_FETCH_W ||
++                   zo->opcode == ZEND_FETCH_IS ||
++                   zo->opcode == ZEND_FETCH_FUNC_ARG
++                  ) {
++                    APC_PREPARE_FETCH_GLOBAL_FOR_EXECUTION();
++                }
 +
-+SOURCE=.\apc_zend.c
-+# End Source File
-+# Begin Source File
++                i--;
++                zo++;
++            }
++        }
++    }
++    return 1;
++}
++/* }}} */
 +
-+SOURCE=.\php_apc.c
-+# End Source File
-+# End Group
-+# Begin Group "Header Files"
++/* {{{ apc_copy_op_array_for_execution */
++zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC)
++{
++    if(dst == NULL) {
++        dst = (zend_op_array*) emalloc(sizeof(src[0]));
++    }
++    memcpy(dst, src, sizeof(src[0]));
++    dst->static_variables = my_copy_static_variables(src, ctxt);
 +
-+# PROP Default_Filter "h;hpp;hxx;hm;inl"
-+# Begin Source File
++    /* memory leak */
++    dst->refcount = apc_pmemcpy(src->refcount,
++                                      sizeof(src->refcount[0]),
++                                      ctxt->pool);
 +
-+SOURCE=.\apc.h
-+# End Source File
-+# Begin Source File
++    my_prepare_op_array_for_execution(dst,src, ctxt TSRMLS_CC);
 +
-+SOURCE=.\apc_cache.h
-+# End Source File
-+# Begin Source File
++    return dst;
++}
++/* }}} */
 +
-+SOURCE=.\apc_compile.h
-+# End Source File
-+# Begin Source File
++/* {{{ apc_copy_function_for_execution */
++zend_function* apc_copy_function_for_execution(zend_function* src, apc_context_t* ctxt)
++{
++    zend_function* dst;
++    TSRMLS_FETCH();
 +
-+SOURCE=.\apc_debug.h
-+# End Source File
-+# Begin Source File
++    dst = (zend_function*) emalloc(sizeof(src[0]));
++    memcpy(dst, src, sizeof(src[0]));
++    apc_copy_op_array_for_execution(&(dst->op_array), &(src->op_array), ctxt TSRMLS_CC);
++    return dst;
++}
++/* }}} */
 +
-+SOURCE=.\apc_fcntl.h
-+# End Source File
-+# Begin Source File
++/* {{{ apc_copy_function_for_execution_ex */
++zend_function* apc_copy_function_for_execution_ex(void *dummy, zend_function* src, apc_context_t* ctxt)
++{
++    if(src->type==ZEND_INTERNAL_FUNCTION || src->type==ZEND_OVERLOADED_FUNCTION) return src;
++    return apc_copy_function_for_execution(src, ctxt);
++}
++/* }}} */
 +
-+SOURCE=.\apc_globals.h
-+# End Source File
-+# Begin Source File
++/* {{{ apc_copy_class_entry_for_execution */
++zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, apc_context_t* ctxt)
++{
++    zend_class_entry* dst = (zend_class_entry*) apc_pool_alloc(ctxt->pool, sizeof(src[0]));
++    memcpy(dst, src, sizeof(src[0]));
 +
-+SOURCE=.\apc_lock.h
-+# End Source File
-+# Begin Source File
++    if(src->num_interfaces)
++    {
++        /* These are slots to be populated later by ADD_INTERFACE insns */
++        dst->interfaces = apc_php_malloc(
++                            sizeof(zend_class_entry*) * src->num_interfaces);
++        memset(dst->interfaces, 0, 
++                            sizeof(zend_class_entry*) * src->num_interfaces);
++    }
++    else
++    {
++        /* assert(dst->interfaces == NULL); */
++    }
 +
-+SOURCE=.\apc_main.h
-+# End Source File
-+# Begin Source File
++    /* Deep-copy the class properties, because they will be modified */
 +
-+SOURCE=.\apc_php.h
-+# End Source File
-+# Begin Source File
++    my_copy_hashtable(&dst->default_properties,
++                      &src->default_properties,
++                      (ht_copy_fun_t) my_copy_zval_ptr,
++                      1,
++                      ctxt);
 +
-+SOURCE=.\apc_shm.h
-+# End Source File
-+# Begin Source File
++    /* For derived classes, we must also copy the function hashtable (although
++     * we can merely bitwise copy the functions it contains) */
 +
-+SOURCE=.\apc_sma.h
-+# End Source File
-+# Begin Source File
++    my_copy_hashtable(&dst->function_table,
++                      &src->function_table,
++                      (ht_copy_fun_t) apc_copy_function_for_execution_ex,
++                      0,
++                      ctxt);
 +
-+SOURCE=.\apc_stack.h
-+# End Source File
-+# Begin Source File
++    my_fixup_hashtable(&dst->function_table, (ht_fixup_fun_t)my_fixup_function_for_execution, src, dst);
 +
-+SOURCE=.\apc_zend.h
-+# End Source File
-+# Begin Source File
++    /* zend_do_inheritance merges properties_info.
++     * Need only shallow copying as it doesn't hold the pointers.
++     */
++    my_copy_hashtable(&dst->properties_info,
++                      &src->properties_info,
++                      (ht_copy_fun_t) my_copy_property_info_for_execution,
++                      0,
++                      ctxt);
 +
-+SOURCE=.\php_apc.h
-+# End Source File
-+# End Group
-+# Begin Group "Resource Files"
++#ifdef ZEND_ENGINE_2_2
++    /* php5.2 introduced a scope attribute for property info */
++    my_fixup_hashtable(&dst->properties_info, (ht_fixup_fun_t)my_fixup_property_info_for_execution, src, dst);
++#endif
 +
-+# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
-+# End Group
-+# End Target
-+# End Project
-diff -ubrN php-5.2.5-orig/ext/apc/apc_fcntl.c php-5.2.5/ext/apc/apc_fcntl.c
---- php-5.2.5-orig/ext/apc/apc_fcntl.c 1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_fcntl.c      2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,118 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: George Schlossnagle <george@omniti.com>                     |
-+  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  +----------------------------------------------------------------------+
++    /* if inheritance results in a hash_del, it might result in
++     * a pefree() of the pointers here. Deep copying required. 
++     */
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++    my_copy_hashtable(&dst->constants_table,
++                      &src->constants_table,
++                      (ht_copy_fun_t) my_copy_zval_ptr,
++                      1,
++                      ctxt);
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++    my_copy_hashtable(&dst->default_static_members,
++                      &src->default_static_members,
++                      (ht_copy_fun_t) my_copy_zval_ptr,
++                      1,
++                      ctxt);
 +
-+ */
++    if(src->static_members != &(src->default_static_members))
++    {
++        dst->static_members = my_copy_hashtable(NULL,
++                          src->static_members,
++                          (ht_copy_fun_t) my_copy_zval_ptr,
++                          1,
++                          ctxt);
++    }
++    else 
++    {
++        dst->static_members = &(dst->default_static_members);
++    }
 +
-+/* $Id: apc_fcntl.c,v 3.25 2006/06/19 02:52:49 rasmus Exp $ */
 +
-+#include "apc_fcntl.h"
-+#include "apc.h"
-+#include <unistd.h>
-+#include <fcntl.h>
++    return dst;
++}
++/* }}} */
 +
-+int apc_fcntl_create(const char* pathname)
++/* {{{ apc_free_class_entry_after_execution */
++void apc_free_class_entry_after_execution(zend_class_entry* src)
 +{
-+    int fd;
-+    if(pathname == NULL) {
-+        char lock_path[] = "/tmp/.apc.XXXXXX";
-+        mktemp(lock_path);
-+        fd = open(lock_path, O_RDWR|O_CREAT, 0666);
-+        if(fd > 0 ) {
-+            unlink(lock_path);
-+            return fd;
-+        } else {
-+            apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", lock_path);
-+            return -1;
-+        }
++    if(src->num_interfaces > 0 && src->interfaces) {
++        apc_php_free(src->interfaces);
++        src->interfaces = NULL;
++        src->num_interfaces = 0;
 +    }
-+    fd = open(pathname, O_RDWR|O_CREAT, 0666);
-+    if(fd > 0 ) {
-+        unlink(pathname);
-+        return fd;
++    /* my_destroy_hashtable() does not play nice with refcounts */
++
++    zend_hash_clean(&src->default_static_members);
++    if(src->static_members != &(src->default_static_members))
++    {
++        zend_hash_destroy(src->static_members);
++        apc_php_free(src->static_members);
++        src->static_members = NULL;
 +    }
-+    apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
-+    return -1;
-+}
++    else
++    {
++        src->static_members = NULL;
++    }
++    zend_hash_clean(&src->default_properties);
++    zend_hash_clean(&src->constants_table);
 +
-+void apc_fcntl_destroy(int fd)
-+{
-+    close(fd);
++    /* TODO: more cleanup */
 +}
++/* }}} */
 +
-+static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
++/* {{{ apc_file_halt_offset */
++long apc_file_halt_offset(const char *filename)
 +{
-+  int ret;
-+  struct flock lock;
++    zend_constant *c;
++    char *name;
++    int len;
++    char haltoff[] = "__COMPILER_HALT_OFFSET__";
++    long value = -1;
++    TSRMLS_FETCH();
 +
-+  lock.l_type = type;
-+  lock.l_start = offset;
-+  lock.l_whence = whence;
-+  lock.l_len = len;
-+  lock.l_pid = 0;
++    zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, filename, strlen(filename), 0);
++    
++    if (zend_hash_find(EG(zend_constants), name, len+1, (void **) &c) == SUCCESS) {
++        value = Z_LVAL(c->value);
++    }
++    
++    pefree(name, 0);
 +
-+  do { ret = fcntl(fd, cmd, &lock) ; }
-+  while(ret < 0 && errno == EINTR);
-+  return(ret);
++    return value;
 +}
++/* }}} */
 +
-+void apc_fcntl_lock(int fd)
++/* {{{ apc_do_halt_compiler_register */
++void apc_do_halt_compiler_register(const char *filename, long halt_offset TSRMLS_DC)
 +{
-+    if(lock_reg(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
-+        apc_eprint("apc_fcntl_lock failed:");
++    char *name;
++    char haltoff[] = "__COMPILER_HALT_OFFSET__";
++    int len;
++   
++    if(halt_offset > 0) {
++        
++        zend_mangle_property_name(&name, &len, haltoff, sizeof(haltoff) - 1, 
++                                    filename, strlen(filename), 0);
++        
++        zend_register_long_constant(name, len+1, halt_offset, CONST_CS, 0 TSRMLS_CC);
++
++        pefree(name, 0);
 +    }
 +}
++/* }}} */
 +
-+void apc_fcntl_rdlock(int fd)
++
++
++/* {{{ my_fixup_function */
++static void my_fixup_function(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
 +{
-+    if(lock_reg(fd, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) {
-+        apc_eprint("apc_fcntl_rdlock failed:");
++    zend_function* zf = p->pData;
++
++    #define SET_IF_SAME_NAME(member) \
++    do { \
++        if(src->member && !strcmp(zf->common.function_name, src->member->common.function_name)) { \
++            dst->member = zf; \
++        } \
++    } \
++    while(0)
++
++    if(zf->common.scope == src)
++    {
++
++        /* Fixing up the default functions for objects here since
++         * we need to compare with the newly allocated functions
++         *
++         * caveat: a sub-class method can have the same name as the
++         * parent's constructor and create problems.
++         */
++
++        if(zf->common.fn_flags & ZEND_ACC_CTOR) dst->constructor = zf;
++        else if(zf->common.fn_flags & ZEND_ACC_DTOR) dst->destructor = zf;
++        else if(zf->common.fn_flags & ZEND_ACC_CLONE) dst->clone = zf;
++        else
++        {
++            SET_IF_SAME_NAME(__get);
++            SET_IF_SAME_NAME(__set);
++            SET_IF_SAME_NAME(__unset);
++            SET_IF_SAME_NAME(__isset);
++            SET_IF_SAME_NAME(__call);
++#ifdef ZEND_ENGINE_2_2
++            SET_IF_SAME_NAME(__tostring);
++#endif
++#ifdef ZEND_ENGINE_2_3
++            SET_IF_SAME_NAME(__callstatic);
++#endif
++        }
++        zf->common.scope = dst;
++    }
++    else
++    {
++        /* no other function should reach here */
++        assert(0);
 +    }
++
++    #undef SET_IF_SAME_NAME
 +}
++/* }}} */
 +
-+zend_bool apc_fcntl_nonblocking_lock(int fd)
++#ifdef ZEND_ENGINE_2_2
++/* {{{ my_fixup_property_info */
++static void my_fixup_property_info(Bucket *p, zend_class_entry *src, zend_class_entry *dst)
 +{
-+    if(lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0) < 0) {
-+        if(errno==EACCES||errno==EAGAIN) return 0;
-+        else apc_eprint("apc_fcntl_lock failed:");
++    zend_property_info* property_info = (zend_property_info*)p->pData;
++
++    if(property_info->ce == src)
++    {
++        property_info->ce = dst;
++    }
++    else
++    {
++        assert(0); /* should never happen */
 +    }
-+    return 1;
 +}
++/* }}} */
++#endif
 +
-+void apc_fcntl_unlock(int fd)
++/* {{{ my_fixup_hashtable */
++static void my_fixup_hashtable(HashTable *ht, ht_fixup_fun_t fixup, zend_class_entry *src, zend_class_entry *dst)
 +{
-+    if(lock_reg(fd, F_SETLKW, F_UNLCK, 0, SEEK_SET, 0) < 0) {
-+        apc_eprint("apc_fcntl_unlock failed:");
++    Bucket *p;
++    uint i;
++
++    for (i = 0; i < ht->nTableSize; i++) {
++        if(!ht->arBuckets) break;
++        p = ht->arBuckets[i];
++        while (p != NULL) {
++            fixup(p, src, dst);
++            p = p->pNext;
++        }
 +    }
 +}
++/* }}} */
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_fcntl.h php-5.2.5/ext/apc/apc_fcntl.h
---- php-5.2.5-orig/ext/apc/apc_fcntl.h 1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_fcntl.h      2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,50 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt.                                 |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: George Schlossnagle <george@omniti.com>                     |
-+  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  +----------------------------------------------------------------------+
-+
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++/* {{{ my_check_copy_function */
++static int my_check_copy_function(Bucket* p, va_list args)
++{
++    zend_class_entry* src = va_arg(args, zend_class_entry*);
++    zend_function* zf = (zend_function*)p->pData;
 +
-+ */
++    return (zf->common.scope == src);
++}
++/* }}} */
 +
-+/* $Id: apc_fcntl.h,v 3.14 2006/05/31 22:24:48 rasmus Exp $ */
++/* {{{ my_check_copy_default_property */
++static int my_check_copy_default_property(Bucket* p, va_list args)
++{
++    zend_class_entry* src = va_arg(args, zend_class_entry*);
++    zend_class_entry* parent = src->parent;
++    zval ** child_prop = (zval**)p->pData;
++    zval ** parent_prop = NULL;
 +
-+#ifndef APC_FCNTL_H
-+#define APC_FCNTL_H
++    if (parent &&
++        zend_hash_quick_find(&parent->default_properties, p->arKey, 
++            p->nKeyLength, p->h, (void **) &parent_prop)==SUCCESS) {
 +
++        if((parent_prop && child_prop) && (*parent_prop) == (*child_prop))
++        {
++            return 0;
++        }
++    }
 +
-+extern int apc_fcntl_create(const char* pathname);
-+extern void apc_fcntl_destroy(int fd);
-+extern void apc_fcntl_lock(int fd);
-+extern void apc_fcntl_rdlock(int fd);
-+extern void apc_fcntl_unlock(int fd);
-+extern unsigned char apc_fcntl_nonblocking_lock(int fd);
-+#endif
++    /* possibly not in the parent */
++    return 1;
++}
++/* }}} */
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_fcntl_win32.c php-5.2.5/ext/apc/apc_fcntl_win32.c
---- php-5.2.5-orig/ext/apc/apc_fcntl_win32.c   1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_fcntl_win32.c        2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,117 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: George Schlossnagle <george@omniti.com>                     |
-+  |          Edin Kadribasic <edink@php.net>                             |
-+  +----------------------------------------------------------------------+
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++/* {{{ my_check_copy_property_info */
++static int my_check_copy_property_info(Bucket* p, va_list args)
++{
++    zend_class_entry* src = va_arg(args, zend_class_entry*);
++    zend_class_entry* parent = src->parent;
++    zend_property_info* child_info = (zend_property_info*)p->pData;
++    zend_property_info* parent_info = NULL;
 +
-+   All other licensing and usage conditions are those of the PHP Group.
-+
-+ */
++#ifdef ZEND_ENGINE_2_2
++    /* so much easier */
++    return (child_info->ce == src);
++#endif
 +
-+/* $Id: apc_fcntl_win32.c,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
++    if (parent &&
++        zend_hash_quick_find(&parent->properties_info, p->arKey, p->nKeyLength,
++            p->h, (void **) &parent_info)==SUCCESS) {
++        if(parent_info->flags & ZEND_ACC_PRIVATE)
++        {
++            return 1;
++        }
++        if((parent_info->flags & ZEND_ACC_PPP_MASK) !=
++            (child_info->flags & ZEND_ACC_PPP_MASK))
++        {
++            /* TODO: figure out whether ACC_CHANGED is more appropriate
++             * here */
++            return 1;
++        }
++        return 0;
++    }
 +
-+#include "apc_fcntl.h"
-+#include "apc.h"
-+#include <php.h>
-+#include <win32/flock.h>
-+#include <io.h>
-+#include <fcntl.h>
-+#include <sys/types.h>
-+#include <sys/stat.h>
++    /* property doesn't exist in parent, copy into cached child */
++    return 1;
++}
++/* }}} */
 +
-+int apc_fcntl_create(const char* pathname)
++/* {{{ my_check_copy_static_member */
++static int my_check_copy_static_member(Bucket* p, va_list args)
 +{
-+      char *lock_file = emalloc(MAXPATHLEN);
-+      HANDLE fd;
-+      DWORD tmplen;
-+      static int i=0;
-+      
-+      tmplen = GetTempPath(MAXPATHLEN, lock_file);
-+      if (!tmplen) {
-+              efree(lock_file);
-+              return -1;
-+      }
++    zend_class_entry* src = va_arg(args, zend_class_entry*);
++    HashTable * ht = va_arg(args, HashTable*);
++    zend_class_entry* parent = src->parent;
++    HashTable * parent_ht = NULL;
++    char * member_name;
++    char * class_name = NULL;
 +
-+      snprintf(lock_file + tmplen, MAXPATHLEN - tmplen - 1, "apc.lock.%d", i++);
-+      
-+      fd = CreateFile(lock_file,
-+        GENERIC_READ | GENERIC_WRITE,
-+        FILE_SHARE_READ | FILE_SHARE_WRITE,
-+        NULL,
-+        OPEN_ALWAYS,
-+        FILE_ATTRIBUTE_NORMAL,
-+        NULL);
-+        
++    zend_property_info *parent_info = NULL;
++    zend_property_info *child_info = NULL;
++    zval ** parent_prop = NULL;
++    zval ** child_prop = (zval**)(p->pData);
 +
-+      if (fd == INVALID_HANDLE_VALUE) {
-+              apc_eprint("apc_fcntl_create: could not open %s", lock_file);
-+              efree(lock_file);
-+              return -1;
-+      }
-+      
-+      efree(lock_file);
-+      return (int)fd;
-+}
++    if(!parent) {
++        return 1;
++    }
 +
-+void apc_fcntl_destroy(int fd)
-+{
-+      CloseHandle((HANDLE)fd);
-+}
++    /* these do not need free'ing */
++#ifdef ZEND_ENGINE_2_2
++    zend_unmangle_property_name(p->arKey, p->nKeyLength-1, &class_name, &member_name);
++#else
++    zend_unmangle_property_name(p->arKey, &class_name, &member_name);
++#endif
 +
-+void apc_fcntl_lock(int fd)
-+{
-+      OVERLAPPED offset =     {0, 0, 0, 0, NULL};
-+      
-+      if (!LockFileEx((HANDLE)fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset)) {
-+              apc_eprint("apc_fcntl_lock failed errno:%d", GetLastError());
-+      }
-+}
++    /* please refer do_inherit_property_access_check in zend_compile.c
++     * to understand why we lookup in properties_info.
++     */
++    if((zend_hash_find(&parent->properties_info, member_name,
++                        strlen(member_name)+1, (void**)&parent_info) == SUCCESS)
++        &&
++        (zend_hash_find(&src->properties_info, member_name,
++                        strlen(member_name)+1, (void**)&child_info) == SUCCESS))
++    {
++        if(child_info->flags & ZEND_ACC_STATIC &&
++            (parent_info->flags & ZEND_ACC_PROTECTED &&
++            child_info->flags & ZEND_ACC_PUBLIC))
++        {
++            /* Do not copy into static_members. zend_do_inheritance
++             * will automatically insert a NULL value.
++             * TODO: decrement refcount or fixup when copying out for exec ?
++             */ 
++            return 0;
++        }
++        if(ht == &(src->default_static_members))
++        {
++            parent_ht = &parent->default_static_members;
++        }
++        else
++        {
++            parent_ht = parent->static_members;
++        }
 +
-+void apc_fcntl_rdlock(int fd)
-+{
-+      OVERLAPPED offset =     {0, 0, 0, 0, NULL};
-+      
-+      if (!LockFileEx((HANDLE)fd, 0, 0, 1, 0, &offset)) {
-+              apc_eprint("apc_fcntl_rdlock failed errno:%d", GetLastError());
-+      }
-+}
++        if(zend_hash_quick_find(parent_ht, p->arKey,
++                       p->nKeyLength, p->h, (void**)&parent_prop) == SUCCESS)
++        {
++            /* they point to the same zval */
++            if(*parent_prop == *child_prop)
++            {
++                return 0;
++            }
++        }
++    }
 +
-+void apc_fcntl_unlock(int fd)
-+{
-+      OVERLAPPED offset =     {0, 0, 0, 0, NULL};
++    return 1;
++}
++/* }}} */
 +
-+      if (!UnlockFileEx((HANDLE)fd, 0, 1, 0, &offset)) {
-+              DWORD error_code = GetLastError();
-+              /* Ignore already unlocked error */
-+              if (error_code != ERROR_NOT_LOCKED) {
-+                      apc_eprint("apc_fcntl_unlock failed errno:%d", error_code);
-+              }
-+      }
++/* {{{ apc_register_optimizer(apc_optimize_function_t optimizer)
++ *      register a optimizer callback function, returns the previous callback
++ */
++apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC) {
++    apc_optimize_function_t old_optimizer = APCG(apc_optimize_function);
++    APCG(apc_optimize_function) = optimizer;
++    return old_optimizer;
 +}
++/* }}} */
 +
 +/*
 + * Local variables:
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_futex.c php-5.2.5/ext/apc/apc_futex.c
---- php-5.2.5-orig/ext/apc/apc_futex.c 1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_futex.c      2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,116 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_compile.h php-5.3.1/ext/apc/apc_compile.h
+--- php-5.3.1.orig/ext/apc/apc_compile.h       1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_compile.h    1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,142 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -5482,97 +5020,123 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_futex.c php-5.2.5/ext/apc/apc_futex.c
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Brian Shire <shire@php.net>                                 |
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
++  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
 +  +----------------------------------------------------------------------+
 +
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
++
++   All other licensing and usage conditions are those of the PHP Group.
++
 + */
 +
-+/* $Id: apc_futex.c,v 3.2 2006/10/12 08:23:16 shire Exp $ */
-+
-+/***************************************************************************
-+* Futex (Fast Userspace Mutex) support for APC
-+* 
-+* Futex support provides user space locking with system calls only
-+* for the contended cases.  Some required reading for this functionality is:
-+*
-+* 'Fuss, Futexes and Furwocks: Fast Userlevel Locking in Linux' 
-+*  by Hubertus Franke, Rusty Russell, and Matthew Kirkwood
-+*   http://www.realitydiluted.com/nptl-uclibc/docs/futex.pdf
-+*
-+* 'Futexes are Tricky' by Ulrich Drepper 
-+*    http://people.redhat.com/drepper/futex.pdf
-+*
-+* 
-+* This implementation is optimized and designed for the i386 and x86_64 
-+* architectures.  Other architectures may require additional design 
-+* to efficiently and safely implement this functionality. 
-+*
-+* Lock values are:
-+* 0 = Unlocked
-+* 1 = Locked without any waiting processes
-+* 2 = Locked with an unknown number of waiting processes
-+*
-+***************************************************************************/
++/* $Id: apc_compile.h 275218 2009-02-05 13:16:06Z gopalv $ */
++
++#ifndef APC_COMPILE_H
++#define APC_COMPILE_H
++
++/*
++ * This module encapsulates most of the complexity involved in deep-copying
++ * the Zend compiler data structures. The routines are allocator-agnostic, so
++ * the same function can be used for copying to and from shared memory.
++ */
 +
 +#include "apc.h"
-+#include "apc_futex.h"
++#include "apc_php.h"
++#include "apc_main.h"
 +
-+#ifdef APC_FUTEX_LOCKS
++/* {{{ struct definition: apc_function_t */
++typedef struct apc_function_t apc_function_t;
++struct apc_function_t {
++    char* name;                 /* the function name */
++    int name_len;               /* length of name */
++    zend_function* function;    /* the zend function data structure */
++};
++/* }}} */
 +
++/* {{{ struct definition: apc_class_t */
++typedef struct apc_class_t apc_class_t;
++struct apc_class_t {
++    char* name;                     /* the class name */
++    int name_len;                   /* length of name */
++    char* parent_name;              /* the parent class name */
++    zend_class_entry* class_entry;  /* the zend class data structure */
++};
++/* }}} */
 +
-+inline int apc_futex_create()
-+{
-+    return 0;
-+}
++/* {{{ struct definition: apc_opflags_t */
++typedef struct apc_opflags_t apc_opflags_t;
++struct apc_opflags_t {
++    unsigned int has_jumps      : 1; /* has jump offsets */
++    unsigned int deep_copy      : 1; /* needs deep copy */
 +
-+inline void apc_futex_destroy(volatile int* lock)
-+{
-+    return;
-+}
++    /* autoglobal bits */
++    unsigned int _POST          : 1;
++    unsigned int _GET           : 1;
++    unsigned int _COOKIE        : 1;
++    unsigned int _SERVER        : 1;
++    unsigned int _ENV           : 1;
++    unsigned int _FILES         : 1;
++    unsigned int _REQUEST       : 1;
++    unsigned int unknown_global : 1;
++};
++/* }}} */
 +
-+void apc_futex_lock(volatile int* lock)
-+{
-+    int c;
-+  
-+    /*  Attempt to obtain a lock if not currently locked.  If the previous
-+     *  value was not 0 then we did not obtain the lock, and must wait.
-+     *  If the previous value was 1 (has no waiting processes) then we
-+     *  set the lock to 2 before blocking on the futex wait operation.  
-+     *  This implementation suffers from the possible difficulty of 
-+     *  efficently implementing the atomic xchg operation on some
-+     *  architectures, and could also cause unecessary wake operations by
-+     *  setting the lock to 2 when there are no additional waiters.
-+     */ 
-+    if((c = apc_cmpxchg(lock, 0, 1)) != 0) {
-+        if(c != 2) {
-+            c = apc_xchg(lock, 2);
-+        }
-+        while(c != 0) {
-+            apc_futex_wait(lock, 2);
-+            c = apc_xchg(lock, 2);
-+        }
-+    }
-+    
-+}
++/*
++ * These are the top-level copy functions.
++ */
 +
-+/* non-blocking lock returns 1 when the lock has been obtained, 0 if it would block */
-+inline zend_bool apc_futex_nonblocking_lock(volatile int* lock)
-+{
-+    return apc_cmpxchg(lock, 0, 1) == 0;
-+}
++extern zend_op_array* apc_copy_op_array(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC);
++extern zend_class_entry* apc_copy_class_entry(zend_class_entry* dst, zend_class_entry* src, apc_context_t* ctxt);
++extern apc_function_t* apc_copy_new_functions(int old_count, apc_context_t* ctxt TSRMLS_DC);
++extern apc_class_t* apc_copy_new_classes(zend_op_array* op_array, int old_count, apc_context_t* ctxt TSRMLS_DC);
++extern zval* apc_copy_zval(zval* dst, const zval* src, apc_context_t* ctxt);
++
++#if 0
++/*
++ * Deallocation functions corresponding to the copy functions above.
++ */
 +
++extern void apc_free_op_array(zend_op_array* src, apc_context_t* ctxt);
++extern void apc_free_functions(apc_function_t* src, apc_context_t* ctxt);
++extern void apc_free_classes(apc_class_t* src, apc_context_t* ctxt);
++extern void apc_free_zval(zval* src, apc_context_t* ctxt);
++#endif
 +
-+inline void apc_futex_unlock(volatile int* lock)
-+{
-+    /* set the lock to 0, if it's previous values was not 1 (no waiters)
-+     * then perform a wake operation on one process letting it know the lock 
-+     * is available.  This is an optimization to save wake calls if there
-+     * are no waiting processes for the lock 
-+     */
-+    if(apc_xchg(lock,0) != 1) {
-+        apc_futex_wake(lock, 1);
-+    }
-+}
++/*
++ * These "copy-for-execution" functions must be called after retrieving an
++ * object from the shared cache. They do the minimal amount of work necessary
++ * to allow multiple processes to concurrently execute the same VM data
++ * structures.
++ */
++
++extern zend_op_array* apc_copy_op_array_for_execution(zend_op_array* dst, zend_op_array* src, apc_context_t* ctxt TSRMLS_DC);
++extern zend_function* apc_copy_function_for_execution(zend_function* src, apc_context_t* ctxt);
++extern zend_class_entry* apc_copy_class_entry_for_execution(zend_class_entry* src, apc_context_t* ctxt);
++
++/*
++ * The "free-after-execution" function performs a cursory clean up of the class data
++ * This is required to minimize memory leak warnings and to ensure correct destructor
++ * ordering of some variables.
++ */
++extern void apc_free_class_entry_after_execution(zend_class_entry* src);
++
++/*
++ * Optimization callback definition and registration function. 
++ */
++typedef zend_op_array* (*apc_optimize_function_t) (zend_op_array* TSRMLS_DC);
++extern apc_optimize_function_t apc_register_optimizer(apc_optimize_function_t optimizer TSRMLS_DC);
++
++/*
++ * To handle __COMPILER_HALT_OFFSET__
++ */
++long apc_file_halt_offset(const char* filename);
++void apc_do_halt_compiler_register(const char *filename, long halt_offset TSRMLS_DC);
 +
 +#endif
 +
@@ -5581,18 +5145,18 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_futex.c php-5.2.5/ext/apc/apc_futex.c
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_futex.h php-5.2.5/ext/apc/apc_futex.h
---- php-5.2.5-orig/ext/apc/apc_futex.h 1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_futex.h      2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,55 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_debug.c php-5.3.1/ext/apc/apc_debug.c
+--- php-5.3.1.orig/ext/apc/apc_debug.c 1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_debug.c      1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,57 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -5602,70 +5166,285 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_futex.h php-5.2.5/ext/apc/apc_futex.h
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Brian Shire <shire@php.net>                                 |
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
++  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
 +  +----------------------------------------------------------------------+
 +
-+ */
-+
-+/* $Id: apc_futex.h,v 3.2 2006/10/12 08:23:16 shire Exp $ */
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
 +
-+#ifndef APC_FUTEX_H
-+#define APC_FUTEX_H
++   All other licensing and usage conditions are those of the PHP Group.
++*/
 +
++/* $Id: apc_debug.c 268255 2008-11-04 05:42:11Z rasmus $ */
 +#include "apc.h"
++#include <stdio.h>
++#include "zend_compile.h"
 +
-+#ifdef APC_FUTEX_LOCKS 
++#ifdef __DEBUG_APC__
 +
-+#include <asm/types.h>
-+#include <unistd.h>
-+#include <linux/futex.h>
++#include <dlfcn.h>
 +
-+#include "arch/atomic.h"
++/* keep track of vld_dump_oparray() signature */
++typedef void (*vld_dump_f) (zend_op_array * TSRMLS_DC);
 +
-+#define sys_futex(futex, op, val, timeout) syscall(SYS_futex, futex, op, val, timeout)
-+#define apc_futex_wait(val, oldval) sys_futex((void*)val, FUTEX_WAIT, oldval, NULL)
-+#define apc_futex_wake(val, count) sys_futex((void*)val, FUTEX_WAKE, count, NULL)
++#endif
 +
-+int apc_futex_create();
-+void apc_futex_destroy(volatile int* lock);
-+void apc_futex_lock(volatile int* lock);
-+void apc_futex_unlock(volatile int* lock);
++void dump(zend_op_array *op_array TSRMLS_DC)
++{
++#ifdef __DEBUG_APC__
++  vld_dump_f dump_op_array = dlsym(NULL, "vld_dump_oparray");
 +
++  if(dump_op_array)
++  {
++  dump_op_array(op_array TSRMLS_CC); 
++  }
++  else
++  {
++  apc_wprint("vld is not installed or something even worse.");
++  }
 +#endif
++}
+diff -Naur php-5.3.1.orig/ext/apc/apc_debug.h php-5.3.1/ext/apc/apc_debug.h
+--- php-5.3.1.orig/ext/apc/apc_debug.h 1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_debug.h      1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1 @@
++void dump(zend_op_array * TSRMLS_DC);
+diff -Naur php-5.3.1.orig/ext/apc/apc.dsp php-5.3.1/ext/apc/apc.dsp
+--- php-5.3.1.orig/ext/apc/apc.dsp     1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc.dsp  1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,207 @@
++# Microsoft Developer Studio Project File - Name="apc" - Package Owner=<4>
++# Microsoft Developer Studio Generated Build File, Format Version 6.00
++# ** DO NOT EDIT **
 +
-+#endif
++# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_globals.h php-5.2.5/ext/apc/apc_globals.h
---- php-5.2.5-orig/ext/apc/apc_globals.h       1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_globals.h    2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,119 @@
++CFG=apc - Win32 Debug_TS
++!MESSAGE This is not a valid makefile. To build this project using NMAKE,
++!MESSAGE use the Export Makefile command and run
++!MESSAGE 
++!MESSAGE NMAKE /f "apc.mak".
++!MESSAGE 
++!MESSAGE You can specify a configuration when running NMAKE
++!MESSAGE by defining the macro CFG on the command line. For example:
++!MESSAGE 
++!MESSAGE NMAKE /f "apc.mak" CFG="apc - Win32 Debug_TS"
++!MESSAGE 
++!MESSAGE Possible choices for configuration are:
++!MESSAGE 
++!MESSAGE "apc - Win32 Debug_TS" (based on "Win32 (x86) Dynamic-Link Library")
++!MESSAGE "apc - Win32 Release_TS" (based on "Win32 (x86) Dynamic-Link Library")
++!MESSAGE 
++
++# Begin Project
++# PROP AllowPerConfigDependencies 0
++# PROP Scc_ProjName ""
++# PROP Scc_LocalPath ""
++CPP=cl.exe
++MTL=midl.exe
++RSC=rc.exe
++
++!IF  "$(CFG)" == "apc - Win32 Debug_TS"
++
++# PROP BASE Use_MFC 0
++# PROP BASE Use_Debug_Libraries 1
++# PROP BASE Output_Dir "Debug_TS"
++# PROP BASE Intermediate_Dir "Debug_TS"
++# PROP BASE Target_Dir ""
++# PROP Use_MFC 0
++# PROP Use_Debug_Libraries 1
++# PROP Output_Dir "Debug_TS"
++# PROP Intermediate_Dir "Debug_TS"
++# PROP Ignore_Export_Lib 0
++# PROP Target_Dir ""
++# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /GZ /c
++# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\win32" /I "..\..\..\php4\regex" /D "TSRM_LOCKS" /D HAVE_APC=1 /D "COMPILE_DL_APC" /D ZEND_DEBUG=1 /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /GZ /c
++# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
++# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
++# ADD BASE RSC /l 0x409 /d "_DEBUG"
++# ADD RSC /l 0x409 /d "_DEBUG"
++BSC32=bscmake.exe
++# ADD BASE BSC32 /nologo
++# ADD BSC32 /nologo
++LINK32=link.exe
++# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
++# ADD LINK32 php4ts_debug.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /out:"Debug_TS/php_apc.dll" /pdbtype:sept /libpath:"..\..\..\php4\Debug_TS"
++
++!ELSEIF  "$(CFG)" == "apc - Win32 Release_TS"
++
++# PROP BASE Use_MFC 0
++# PROP BASE Use_Debug_Libraries 0
++# PROP BASE Output_Dir "Release_TS"
++# PROP BASE Intermediate_Dir "Release_TS"
++# PROP BASE Target_Dir ""
++# PROP Use_MFC 0
++# PROP Use_Debug_Libraries 0
++# PROP Output_Dir "Release_TS"
++# PROP Intermediate_Dir "Release_TS"
++# PROP Ignore_Export_Lib 0
++# PROP Target_Dir ""
++# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /c
++# ADD CPP /nologo /MT /W3 /GX /O2 /I "..\..\..\php4" /I "..\..\..\php4\main" /I "..\..\..\php4\Zend" /I "..\..\..\php4\TSRM" /I "..\..\..\php4\win32" /I "..\..\..\php4\regex" /D "TSRM_LOCKS" /D HAVE_APC=1 /D "COMPILE_DL_APC" /D ZEND_DEBUG=0 /D ZTS=1 /D "ZEND_WIN32" /D "PHP_WIN32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "APC_EXPORTS" /YX /FD /c
++# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
++# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
++# ADD BASE RSC /l 0x409 /d "NDEBUG"
++# ADD RSC /l 0x409 /d "NDEBUG"
++BSC32=bscmake.exe
++# ADD BASE BSC32 /nologo
++# ADD BSC32 /nologo
++LINK32=link.exe
++# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
++# ADD LINK32 php4ts.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../../Release_TS/php_apc.dll" /libpath:"..\..\..\php4\Release_TS" /libpath:"..\..\..\php4\Release_TS_Inline"
++
++!ENDIF 
++
++# Begin Target
++
++# Name "apc - Win32 Debug_TS"
++# Name "apc - Win32 Release_TS"
++# Begin Group "Source Files"
++
++# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
++# Begin Source File
++
++SOURCE=.\apc.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_cache.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_compile.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_debug.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_fcntl_win32.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_main.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_rfc1867.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_shm.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_sma.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_stack.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_zend.c
++# End Source File
++# Begin Source File
++
++SOURCE=.\php_apc.c
++# End Source File
++# End Group
++# Begin Group "Header Files"
++
++# PROP Default_Filter "h;hpp;hxx;hm;inl"
++# Begin Source File
++
++SOURCE=.\apc.h
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_cache.h
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_compile.h
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_debug.h
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_fcntl.h
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_globals.h
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_lock.h
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_main.h
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_php.h
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_shm.h
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_sma.h
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_stack.h
++# End Source File
++# Begin Source File
++
++SOURCE=.\apc_zend.h
++# End Source File
++# Begin Source File
++
++SOURCE=.\php_apc.h
++# End Source File
++# End Group
++# Begin Group "Resource Files"
++
++# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
++# End Group
++# End Target
++# End Project
+diff -ubrN php-5.2.5-orig/ext/apc/apc_fcntl.c php-5.2.5/ext/apc/apc_fcntl.c
+--- php-5.2.5-orig/ext/apc/apc_fcntl.c 1969-12-31 18:00:00.000000000 -0600
++++ php-5.2.5/ext/apc/apc_fcntl.c      2007-12-26 16:51:32.000000000 -0600
+@@ -0,0 +1,118 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
 +  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt.                                 |
++  | http://www.php.net/license/3_01.txt                                  |
 +  | If you did not receive a copy of the PHP license and are unable to   |
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          George Schlossnagle <george@omniti.com>                     |
++  | Authors: George Schlossnagle <george@omniti.com>                     |
 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
-+  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
 +  +----------------------------------------------------------------------+
 +
 +   This software was contributed to PHP by Community Connect Inc. in 2002
@@ -5678,117 +5457,121 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_globals.h php-5.2.5/ext/apc/apc_globals.h
 +
 + */
 +
-+/* $Id: apc_globals.h,v 3.70 2007/12/26 22:46:33 rasmus Exp $ */
++/* $Id: apc_fcntl.c 268255 2008-11-04 05:42:11Z rasmus $ */
 +
-+#ifndef APC_GLOBALS_H
-+#define APC_GLOBALS_H
++#include "apc.h"
 +
-+#define APC_VERSION "3.0.16"
++#ifdef APC_FCNTL_LOCKS
 +
-+#include "apc_cache.h"
-+#include "apc_stack.h"
-+#include "apc_php.h"
++#include "apc_fcntl.h"
++#include <unistd.h>
++#include <fcntl.h>
 +
-+ZEND_BEGIN_MODULE_GLOBALS(apc)
-+    /* configuration parameters */
-+    zend_bool enabled;      /* if true, apc is enabled (defaults to true) */
-+    long shm_segments;      /* number of shared memory segments to use */
-+    long shm_size;          /* size of each shared memory segment (in MB) */
-+    long num_files_hint;    /* parameter to apc_cache_create */
-+    long user_entries_hint;
-+    long gc_ttl;            /* parameter to apc_cache_create */
-+    long ttl;               /* parameter to apc_cache_create */
-+    long user_ttl;
-+#if APC_MMAP
-+    char *mmap_file_mask;   /* mktemp-style file-mask to pass to mmap */
-+#endif
-+    char** filters;         /* array of regex filters that prevent caching */
++int apc_fcntl_create(const char* pathname)
++{
++    int fd;
++    if(pathname == NULL) {
++        char lock_path[] = "/tmp/.apc.XXXXXX";
++        mktemp(lock_path);
++        fd = open(lock_path, O_RDWR|O_CREAT, 0666);
++        if(fd > 0 ) {
++            unlink(lock_path);
++            return fd;
++        } else {
++            apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", lock_path);
++            return -1;
++        }
++    }
++    fd = open(pathname, O_RDWR|O_CREAT, 0666);
++    if(fd > 0 ) {
++        unlink(pathname);
++        return fd;
++    }
++    apc_eprint("apc_fcntl_create: open(%s, O_RDWR|O_CREAT, 0666) failed:", pathname);
++    return -1;
++}
 +
-+    /* module variables */
-+    zend_bool initialized;       /* true if module was initialized */
-+    apc_stack_t* cache_stack;    /* the stack of cached executable code */
-+    zend_bool cache_by_default;  /* true if files should be cached unless filtered out */
-+                                 /* false if files should only be cached if filtered in */
-+    long slam_defense;           /* Probability of a process not caching an uncached file */
-+    size_t* mem_size_ptr;        /* size of blocks allocated to file being cached (NULL outside my_compile_file) */
-+    long file_update_protection; /* Age in seconds before a file is eligible to be cached - 0 to disable */
-+    zend_bool enable_cli;        /* Flag to override turning APC off for CLI */
-+    long max_file_size;                /* Maximum size of file, in bytes that APC will be allowed to cache */
-+    long slam_rand;              /* A place to store the slam rand value for the request */
-+    zend_bool fpstat;            /* true if fullpath includes should be stat'ed */
-+    zend_bool stat_ctime;        /* true if ctime in addition to mtime should be checked */
-+    zend_bool write_lock;        /* true for a global write lock */
-+    zend_bool report_autofilter; /* true for auto-filter warnings */
-+    zend_bool include_once;        /* Override the ZEND_INCLUDE_OR_EVAL opcode handler to avoid pointless fopen()s [still experimental] */
-+    apc_optimize_function_t apc_optimize_function;   /* optimizer function callback */
-+#ifdef MULTIPART_EVENT_FORMDATA
-+    zend_bool rfc1867;           /* Flag to enable rfc1867 handler */
-+    char* rfc1867_prefix;        /* Key prefix */
-+    char* rfc1867_name;          /* Name of hidden field to activate upload progress/key suffix */
-+    double rfc1867_freq;         /* Update frequency as percentage or bytes */
-+#endif
-+    HashTable *copied_zvals;     /* my_copy recursion detection list */
-+#ifdef ZEND_ENGINE_2
-+    int reserved_offset;         /* offset for apc info in op_array->reserved[] */
-+#endif
-+    zend_bool localcache;        /* enable local cache */
-+    long localcache_size;        /* size of fast cache */
-+    apc_local_cache_t* lcache;   /* unlocked local cache */
-+    zend_bool force_file_update; /* force files to be updated during apc_compile_file */
-+    char canon_path[MAXPATHLEN]; /* canonical path for key data */
-+#if APC_FILEHITS
-+    zval *filehits;             /* Files that came from the cache for this request */
-+#endif
-+    zend_bool coredump_unmap;    /* Trap signals that coredump and unmap shared memory */
-+ZEND_END_MODULE_GLOBALS(apc)
++void apc_fcntl_destroy(int fd)
++{
++    close(fd);
++}
 +
-+/* (the following declaration is defined in php_apc.c) */
-+ZEND_EXTERN_MODULE_GLOBALS(apc)
++static int lock_reg(int fd, int cmd, int type, off_t offset, int whence, off_t len)
++{
++  int ret;
++  struct flock lock;
 +
-+#ifdef ZTS
-+# define APCG(v) TSRMG(apc_globals_id, zend_apc_globals *, v)
-+#else
-+# define APCG(v) (apc_globals.v)
-+#endif
++  lock.l_type = type;
++  lock.l_start = offset;
++  lock.l_whence = whence;
++  lock.l_len = len;
++  lock.l_pid = 0;
 +
-+/* True globals */
-+extern apc_cache_t* apc_cache;       /* the global compiler cache */
-+extern apc_cache_t* apc_user_cache;  /* the global user content cache */
-+extern void* apc_compiled_filters;   /* compiled filters */
++  do { ret = fcntl(fd, cmd, &lock) ; }
++  while(ret < 0 && errno == EINTR);
++  return(ret);
++}
 +
-+#endif
++void apc_fcntl_lock(int fd)
++{
++    if(lock_reg(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0) < 0) {
++        apc_eprint("apc_fcntl_lock failed:");
++    }
++}
++
++void apc_fcntl_rdlock(int fd)
++{
++    if(lock_reg(fd, F_SETLKW, F_RDLCK, 0, SEEK_SET, 0) < 0) {
++        apc_eprint("apc_fcntl_rdlock failed:");
++    }
++}
++
++zend_bool apc_fcntl_nonblocking_lock(int fd)
++{
++    if(lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0) < 0) {
++        if(errno==EACCES||errno==EAGAIN) return 0;
++        else apc_eprint("apc_fcntl_lock failed:");
++    }
++    return 1;
++}
++
++void apc_fcntl_unlock(int fd)
++{
++    if(lock_reg(fd, F_SETLKW, F_UNLCK, 0, SEEK_SET, 0) < 0) {
++        apc_eprint("apc_fcntl_unlock failed:");
++    }
++}
++
++#endif /* APC_FCNTL_LOCKS */
 +
 +/*
 + * Local variables:
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc.h php-5.2.5/ext/apc/apc.h
---- php-5.2.5-orig/ext/apc/apc.h       1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc.h    2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,126 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_fcntl.h php-5.3.1/ext/apc/apc_fcntl.h
+--- php-5.3.1.orig/ext/apc/apc_fcntl.h 1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_fcntl.h      1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,50 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
 +  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
++  | http://www.php.net/license/3_01.txt.                                 |
 +  | If you did not receive a copy of the PHP license and are unable to   |
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          George Schlossnagle <george@omniti.com>                     |
++  | Authors: George Schlossnagle <george@omniti.com>                     |
 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
-+  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
 +  +----------------------------------------------------------------------+
 +
 +   This software was contributed to PHP by Community Connect Inc. in 2002
@@ -5801,121 +5584,172 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc.h php-5.2.5/ext/apc/apc.h
 +
 + */
 +
-+/* $Id: apc.h,v 3.14 2007/03/17 14:01:41 gopalv Exp $ */
++/* $Id: apc_fcntl.h 268255 2008-11-04 05:42:11Z rasmus $ */
 +
-+#ifndef APC_H
-+#define APC_H
++#ifndef APC_FCNTL_H
++#define APC_FCNTL_H
++
++
++extern int apc_fcntl_create(const char* pathname);
++extern void apc_fcntl_destroy(int fd);
++extern void apc_fcntl_lock(int fd);
++extern void apc_fcntl_rdlock(int fd);
++extern void apc_fcntl_unlock(int fd);
++extern unsigned char apc_fcntl_nonblocking_lock(int fd);
++#endif
 +
 +/*
-+ * This module defines utilities and helper functions used elsewhere in APC.
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
 + */
+diff -Naur php-5.3.1.orig/ext/apc/apc_fcntl_win32.c php-5.3.1/ext/apc/apc_fcntl_win32.c
+--- php-5.3.1.orig/ext/apc/apc_fcntl_win32.c   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_fcntl_win32.c        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,117 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: George Schlossnagle <george@omniti.com>                     |
++  |          Edin Kadribasic <edink@php.net>                             |
++  +----------------------------------------------------------------------+
 +
-+/* Commonly needed C library headers. */
-+#include <assert.h>
-+#include <errno.h>
-+#include <stdarg.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+#include <string.h>
-+#include <time.h>
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
 +
-+/* UNIX headers (needed for struct stat) */
++   All other licensing and usage conditions are those of the PHP Group.
++
++ */
++
++/* $Id: apc_fcntl_win32.c 268255 2008-11-04 05:42:11Z rasmus $ */
++
++#include "apc_fcntl.h"
++#include "apc.h"
++#include <php.h>
++#include <win32/flock.h>
++#include <io.h>
++#include <fcntl.h>
 +#include <sys/types.h>
 +#include <sys/stat.h>
-+#ifndef PHP_WIN32
-+#include <unistd.h>
-+#endif
-+
-+#ifdef HAVE_CONFIG_H
-+#include <config.h>
-+#endif
 +
-+#include "php.h"
++int apc_fcntl_create(const char* pathname)
++{
++    char *lock_file = emalloc(MAXPATHLEN);
++    HANDLE fd;
++    DWORD tmplen;
++    static int i=0;
++
++    tmplen = GetTempPath(MAXPATHLEN, lock_file);
++    if (!tmplen) {
++        efree(lock_file);
++        return -1;
++    }
 +
-+/* log levels constants (see apc_log) */
-+enum { APC_DBG, APC_NOTICE, APC_WARNING, APC_ERROR };
++    snprintf(lock_file + tmplen, MAXPATHLEN - tmplen - 1, "apc.lock.%d", i++);
 +
-+/* typedefs for extensible memory allocators */
-+typedef void* (*apc_malloc_t)(size_t);
-+typedef void  (*apc_free_t)  (void*);
++    fd = CreateFile(lock_file,
++        GENERIC_READ | GENERIC_WRITE,
++        FILE_SHARE_READ | FILE_SHARE_WRITE,
++        NULL,
++        OPEN_ALWAYS,
++        FILE_ATTRIBUTE_NORMAL,
++        NULL);
 +
-+/* wrappers for memory allocation routines */
-+extern void* apc_emalloc(size_t n);
-+extern void* apc_erealloc(void* p, size_t n);
-+extern void apc_efree(void* p);
-+extern char* apc_estrdup(const char* s);
-+extern void* apc_xstrdup(const char* s, apc_malloc_t f);
-+extern void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f);
 +
-+/* console display functions */
-+extern void apc_log(int level, const char* fmt, ...);
-+extern void apc_eprint(const char* fmt, ...);
-+extern void apc_wprint(const char* fmt, ...);
-+extern void apc_dprint(const char* fmt, ...);
-+extern void apc_nprint(const char* fmt, ...);
++    if (fd == INVALID_HANDLE_VALUE) {
++        apc_eprint("apc_fcntl_create: could not open %s", lock_file);
++        efree(lock_file);
++        return -1;
++    }
 +
-+/* string and text manipulation */
-+extern char* apc_append(const char* s, const char* t);
-+extern char* apc_substr(const char* s, int start, int length);
-+extern char** apc_tokenize(const char* s, char delim);
++    efree(lock_file);
++    return (int)fd;
++}
 +
-+/* filesystem functions */
++void apc_fcntl_destroy(int fd)
++{
++    CloseHandle((HANDLE)fd);
++}
 +
-+typedef struct apc_fileinfo_t 
++void apc_fcntl_lock(int fd)
 +{
-+    char fullpath[MAXPATHLEN+1];
-+    struct stat st_buf;
-+} apc_fileinfo_t;
++    OVERLAPPED offset = {0, 0, 0, 0, NULL};
 +
-+#ifndef PHP_WIN32
-+#define apc_stat(f, b) stat(f, b)
-+#else
-+#define apc_stat(f, b) apc_win32_stat(f, b TSRMLS_CC)
-+extern int apc_win32_stat(const char *path, struct stat *buf TSRMLS_DC);
-+#endif
-+extern int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo);
++    if (!LockFileEx((HANDLE)fd, LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &offset)) {
++        apc_eprint("apc_fcntl_lock failed errno:%d", GetLastError());
++    }
++}
 +
-+/* regular expression wrapper functions */
-+extern void* apc_regex_compile_array(char* patterns[]);
-+extern void apc_regex_destroy_array(void* p);
-+extern int apc_regex_match_array(void* p, const char* input);
++void apc_fcntl_rdlock(int fd)
++{
++    OVERLAPPED offset = {0, 0, 0, 0, NULL};
 +
-+/* apc_crc32: returns the CRC-32 checksum of the first len bytes in buf */
-+extern unsigned int apc_crc32(const char* buf, int len);
++    if (!LockFileEx((HANDLE)fd, 0, 0, 1, 0, &offset)) {
++        apc_eprint("apc_fcntl_rdlock failed errno:%d", GetLastError());
++    }
++}
 +
-+#define APC_NEGATIVE_MATCH 1
-+#define APC_POSITIVE_MATCH 2
++void apc_fcntl_unlock(int fd)
++{
++    OVERLAPPED offset = {0, 0, 0, 0, NULL};
 +
-+#endif
++    if (!UnlockFileEx((HANDLE)fd, 0, 1, 0, &offset)) {
++        DWORD error_code = GetLastError();
++        /* Ignore already unlocked error */
++        if (error_code != ERROR_NOT_LOCKED) {
++            apc_eprint("apc_fcntl_unlock failed errno:%d", error_code);
++        }
++    }
++}
 +
 +/*
 + * Local variables:
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_lock.h php-5.2.5/ext/apc/apc_lock.h
---- php-5.2.5-orig/ext/apc/apc_lock.h  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_lock.h       2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,105 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_globals.h php-5.3.1/ext/apc/apc_globals.h
+--- php-5.3.1.orig/ext/apc/apc_globals.h       1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_globals.h    1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,143 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
 +  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
++  | http://www.php.net/license/3_01.txt.                                 |
 +  | If you did not receive a copy of the PHP license and are unable to   |
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: George Schlossnagle <george@omniti.com>                     |
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          George Schlossnagle <george@omniti.com>                     |
 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
++  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
++  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
 +  +----------------------------------------------------------------------+
 +
 +   This software was contributed to PHP by Community Connect Inc. in 2002
@@ -5928,92 +5762,127 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_lock.h php-5.2.5/ext/apc/apc_lock.h
 +
 + */
 +
-+/* $Id: apc_lock.h,v 3.20 2007/01/29 07:39:02 shire Exp $ */
++/* $Id: apc_globals.h 284222 2009-07-17 01:23:57Z shire $ */
 +
-+#ifndef APC_LOCK
-+#define APC_LOCK
++#ifndef APC_GLOBALS_H
++#define APC_GLOBALS_H
 +
-+#include "apc_sem.h"
-+#include "apc_fcntl.h"
-+#include "apc_pthreadmutex.h"
-+#include "apc_futex.h"
-+#include "apc_spin.h"
-+#ifdef HAVE_CONFIG_H
-+#include <config.h>
++#include "apc_cache.h"
++#include "apc_stack.h"
++#include "apc_php.h"
++
++/* {{{ struct apc_rfc1867_data */
++
++typedef struct _apc_rfc1867_data apc_rfc1867_data;
++
++struct _apc_rfc1867_data {
++    char tracking_key[64];
++    int  key_length;
++    size_t content_length;
++    char filename[128];
++    char name[64];
++    char *temp_filename;
++    int cancel_upload;
++    double start_time;
++    size_t bytes_processed;
++    size_t prev_bytes_processed;
++    int update_freq;
++    double rate;
++};
++/* }}} */
++
++ZEND_BEGIN_MODULE_GLOBALS(apc)
++    /* configuration parameters */
++    zend_bool enabled;      /* if true, apc is enabled (defaults to true) */
++    long shm_segments;      /* number of shared memory segments to use */
++    long shm_size;          /* size of each shared memory segment (in MB) */
++    long num_files_hint;    /* parameter to apc_cache_create */
++    long user_entries_hint;
++    long gc_ttl;            /* parameter to apc_cache_create */
++    long ttl;               /* parameter to apc_cache_create */
++    long user_ttl;
++#if APC_MMAP
++    char *mmap_file_mask;   /* mktemp-style file-mask to pass to mmap */
 +#endif
++    char** filters;         /* array of regex filters that prevent caching */
++    void* compiled_filters; /* compiled regex filters */
 +
-+#ifdef TSRM_LOCKS
-+#define RDLOCK_AVAILABLE 0
-+#define NONBLOCKING_LOCK_AVAILABLE 0
-+/* quick & dirty: use TSRM mutex locks for now */
-+#define apc_lck_create(a,b,c,d) d=(int)tsrm_mutex_alloc()
-+#define apc_lck_destroy(a)    tsrm_mutex_free((MUTEX_T)a)
-+#define apc_lck_lock(a)       tsrm_mutex_lock((MUTEX_T)a)
-+#define apc_lck_rdlock(a)     tsrm_mutex_lock((MUTEX_T)a)
-+#define apc_lck_unlock(a)     tsrm_mutex_unlock((MUTEX_T)a)
-+#elif defined(APC_SEM_LOCKS)
-+#define RDLOCK_AVAILABLE 0
-+#define NONBLOCKING_LOCK_AVAILABLE 0
-+#define apc_lck_t int
-+#define apc_lck_create(a,b,c,d) d=apc_sem_create(NULL,(b),(c))
-+#define apc_lck_destroy(a)    apc_sem_destroy(a)
-+#define apc_lck_lock(a)       apc_sem_lock(a)
-+#define apc_lck_rdlock(a)     apc_sem_lock(a)
-+#define apc_lck_unlock(a)     apc_sem_unlock(a)
-+#elif defined(APC_PTHREADMUTEX_LOCKS)
-+#define RDLOCK_AVAILABLE 0
-+#define NONBLOCKING_LOCK_AVAILABLE 1
-+#define apc_lck_t pthread_mutex_t 
-+#define apc_lck_create(a,b,c,d) apc_pthreadmutex_create((pthread_mutex_t*)&d)
-+#define apc_lck_destroy(a)    apc_pthreadmutex_destroy(&a)
-+#define apc_lck_lock(a)       apc_pthreadmutex_lock(&a)
-+#define apc_lck_nb_lock(a)    apc_pthreadmutex_nonblocking_lock(&a)
-+#define apc_lck_rdlock(a)     apc_pthreadmutex_lock(&a)
-+#define apc_lck_unlock(a)     apc_pthreadmutex_unlock(&a)
-+#elif defined(APC_FUTEX_LOCKS)
-+#define NONBLOCKING_LOCK_AVAILABLE 1 
-+#define apc_lck_t int 
-+#define apc_lck_create(a,b,c,d) d=apc_futex_create()
-+#define apc_lck_destroy(a)    apc_futex_destroy(&a)
-+#define apc_lck_lock(a)       apc_futex_lock(&a)
-+#define apc_lck_nb_lock(a)    apc_futex_nonblocking_lock(&a)
-+#define apc_lck_rdlock(a)     apc_futex_lock(&a)
-+#define apc_lck_unlock(a)     apc_futex_unlock(&a)
-+#elif defined(APC_SPIN_LOCKS)
-+#define NONBLOCKING_LOCK_AVAILABLE APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE
-+#define apc_lck_t slock_t 
-+#define apc_lck_create(a,b,c,d) apc_slock_create((slock_t*)&(d))
-+#define apc_lck_destroy(a)    apc_slock_destroy(&a)
-+#define apc_lck_lock(a)       apc_slock_lock(&a)
-+#define apc_lck_nb_lock(a)    apc_slock_nonblocking_lock(&a)
-+#define apc_lck_rdlock(a)     apc_slock_lock(&a)
-+#define apc_lck_unlock(a)     apc_slock_unlock(&a)
-+#else
-+#define RDLOCK_AVAILABLE 1
-+#ifdef PHP_WIN32
-+#define NONBLOCKING_LOCK_AVAILABLE 0
-+#else
-+#define NONBLOCKING_LOCK_AVAILABLE 1
++    /* module variables */
++    zend_bool initialized;       /* true if module was initialized */
++    apc_stack_t* cache_stack;    /* the stack of cached executable code */
++    zend_bool cache_by_default;  /* true if files should be cached unless filtered out */
++                                 /* false if files should only be cached if filtered in */
++    long file_update_protection; /* Age in seconds before a file is eligible to be cached - 0 to disable */
++    zend_bool enable_cli;        /* Flag to override turning APC off for CLI */
++    long max_file_size;          /* Maximum size of file, in bytes that APC will be allowed to cache */
++    zend_bool fpstat;            /* true if fullpath includes should be stat'ed */
++    zend_bool canonicalize;      /* true if relative paths should be canonicalized in no-stat mode */
++    zend_bool stat_ctime;        /* true if ctime in addition to mtime should be checked */
++    zend_bool write_lock;        /* true for a global write lock */
++    zend_bool report_autofilter; /* true for auto-filter warnings */
++    zend_bool include_once;      /* Override the ZEND_INCLUDE_OR_EVAL opcode handler to avoid pointless fopen()s [still experimental] */
++    apc_optimize_function_t apc_optimize_function;   /* optimizer function callback */
++#ifdef MULTIPART_EVENT_FORMDATA
++    zend_bool rfc1867;            /* Flag to enable rfc1867 handler */
++    char* rfc1867_prefix;         /* Key prefix */
++    char* rfc1867_name;           /* Name of hidden field to activate upload progress/key suffix */
++    double rfc1867_freq;          /* Update frequency as percentage or bytes */
++    long rfc1867_ttl;             /* TTL for rfc1867 entries */
++    apc_rfc1867_data rfc1867_data;/* Per-request data */
 +#endif
-+#define apc_lck_t int
-+#define apc_lck_create(a,b,c,d) d=apc_fcntl_create((a))
-+#define apc_lck_destroy(a)    apc_fcntl_destroy(a)
-+#define apc_lck_lock(a)       apc_fcntl_lock(a)
-+#define apc_lck_nb_lock(a)    apc_fcntl_nonblocking_lock(a)
-+#define apc_lck_rdlock(a)     apc_fcntl_rdlock(a)
-+#define apc_lck_unlock(a)     apc_fcntl_unlock(a)
++    HashTable copied_zvals;      /* my_copy recursion detection list */
++    zend_bool force_file_update; /* force files to be updated during apc_compile_file */
++    char canon_path[MAXPATHLEN]; /* canonical path for key data */
++#if APC_FILEHITS
++    zval *filehits;              /* Files that came from the cache for this request */
++#endif
++    zend_bool coredump_unmap;    /* Trap signals that coredump and unmap shared memory */
++    apc_cache_t *current_cache;  /* current cache being modified/read */
++    char *preload_path;
++    zend_bool file_md5;           /* record md5 hash of files */
++    void *apc_bd_alloc_ptr;      /* bindump alloc() ptr */
++    void *apc_bd_alloc_ubptr;    /* bindump alloc() upper bound ptr */
++    HashTable apc_bd_alloc_list; /* bindump alloc() ptr list */
++    zend_bool use_request_time;  /* use the SAPI request start time for TTL */
++    zend_bool lazy_functions;        /* enable/disable lazy function loading */
++    HashTable *lazy_function_table;  /* lazy function entry table */
++    zend_bool lazy_classes;          /* enable/disable lazy class loading */
++    HashTable *lazy_class_table;     /* lazy class entry table */
++ZEND_END_MODULE_GLOBALS(apc)
++
++/* (the following declaration is defined in php_apc.c) */
++ZEND_EXTERN_MODULE_GLOBALS(apc)
++
++#ifdef ZTS
++# define APCG(v) TSRMG(apc_globals_id, zend_apc_globals *, v)
++#else
++# define APCG(v) (apc_globals.v)
 +#endif
 +
++/* True globals */
++extern apc_cache_t* apc_cache;       /* the global compiler cache */
++extern apc_cache_t* apc_user_cache;  /* the global user content cache */
++extern void* apc_compiled_filters;   /* compiled filters */
++
 +#endif
-diff -ubrN php-5.2.5-orig/ext/apc/apc_main.c php-5.2.5/ext/apc/apc_main.c
---- php-5.2.5-orig/ext/apc/apc_main.c  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_main.c       2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,701 @@
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc.h php-5.3.1/ext/apc/apc.h
+--- php-5.3.1.orig/ext/apc/apc.h       1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc.h    1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,126 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -6024,6 +5893,7 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_main.c php-5.2.5/ext/apc/apc_main.c
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
 +  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          George Schlossnagle <george@omniti.com>                     |
 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
 +  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
 +  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
@@ -6039,686 +5909,748 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_main.c php-5.2.5/ext/apc/apc_main.c
 +
 + */
 +
-+/* $Id: apc_main.c,v 3.103 2007/11/14 19:46:46 shire Exp $ */
++/* $Id: apc.h 276125 2009-02-19 01:02:59Z shire $ */
 +
-+#include "apc_php.h"
-+#include "apc_main.h"
-+#include "apc.h"
-+#include "apc_lock.h"
-+#include "apc_cache.h"
-+#include "apc_compile.h"
-+#include "apc_globals.h"
-+#include "apc_sma.h"
-+#include "apc_stack.h"
-+#include "apc_zend.h"
-+#include "SAPI.h"
-+#if PHP_API_VERSION <= 20020918
-+#if HAVE_APACHE
-+#ifdef APC_PHP4_STAT
-+#undef XtOffsetOf
-+#include "httpd.h"
-+#endif
-+#endif
++#ifndef APC_H
++#define APC_H
++
++/*
++ * This module defines utilities and helper functions used elsewhere in APC.
++ */
++
++/* Commonly needed C library headers. */
++#include <assert.h>
++#include <errno.h>
++#include <stdarg.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <time.h>
++
++/* UNIX headers (needed for struct stat) */
++#include <sys/types.h>
++#include <sys/stat.h>
++#ifndef PHP_WIN32
++#include <unistd.h>
 +#endif
 +
-+/* {{{ module variables */
++#ifdef HAVE_CONFIG_H
++#include <config.h>
++#endif
 +
-+/* pointer to the original Zend engine compile_file function */
-+typedef zend_op_array* (zend_compile_t)(zend_file_handle*, int TSRMLS_DC);
-+static zend_compile_t *old_compile_file;
++#include "php.h"
++#include "main/php_streams.h"
 +
-+/* }}} */
++/* log levels constants (see my_log) */
++enum { APC_DBG, APC_NOTICE, APC_WARNING, APC_ERROR };
 +
-+/* {{{ get/set old_compile_file (to interact with other extensions that need the compile hook) */
-+static zend_compile_t* set_compile_hook(zend_compile_t *ptr)
-+{
-+    zend_compile_t *retval = old_compile_file;
++/* typedefs for extensible memory allocators */
++typedef void* (*apc_malloc_t)(size_t);
++typedef void  (*apc_free_t)  (void*);
 +
-+    if (ptr != NULL) old_compile_file = ptr;
-+    return retval;
-+}
-+/* }}} */
++/* wrappers for memory allocation routines */
++extern void* apc_emalloc(size_t n);
++extern void* apc_erealloc(void* p, size_t n);
++extern void apc_efree(void* p);
++extern char* apc_estrdup(const char* s);
++extern void* apc_xstrdup(const char* s, apc_malloc_t f);
++extern void* apc_xmemcpy(const void* p, size_t n, apc_malloc_t f);
 +
-+/* {{{ install_function */
-+static int install_function(apc_function_t fn TSRMLS_DC)
-+{
-+    int status =
-+        zend_hash_add(EG(function_table),
-+                      fn.name,
-+                      fn.name_len+1,
-+                      apc_copy_function_for_execution(fn.function),
-+                      sizeof(fn.function[0]),
-+                      NULL);
++/* console display functions */
++extern void apc_eprint(const char* fmt, ...);
++extern void apc_wprint(const char* fmt, ...);
++extern void apc_dprint(const char* fmt, ...);
++extern void apc_nprint(const char* fmt, ...);
 +
-+    if (status == FAILURE) {
-+        /* apc_eprint("Cannot redeclare %s()", fn.name); */
-+    }
++/* string and text manipulation */
++extern char* apc_append(const char* s, const char* t);
++extern char* apc_substr(const char* s, int start, int length);
++extern char** apc_tokenize(const char* s, char delim);
 +
-+    return status;
-+}
-+/* }}} */
++/* filesystem functions */
 +
-+/* {{{ install_class */
-+static int install_class(apc_class_t cl TSRMLS_DC)
++typedef struct apc_fileinfo_t 
 +{
-+    zend_class_entry* class_entry = cl.class_entry;
-+    zend_class_entry* parent = NULL;
-+    int status;
-+#ifdef ZEND_ENGINE_2
-+    zend_class_entry** allocated_ce = NULL;
-+#endif
++    char fullpath[MAXPATHLEN+1];
++    php_stream_statbuf st_buf;
++} apc_fileinfo_t;
 +
++extern int apc_search_paths(const char* filename, const char* path, apc_fileinfo_t* fileinfo);
 +
-+    /* Special case for mangled names. Mangled names are unique to a file.
-+     * There is no way two classes with the same mangled name will occur,
-+     * unless a file is included twice. And if in case, a file is included
-+     * twice, all mangled name conflicts can be ignored and the class redeclaration
-+     * error may be deferred till runtime of the corresponding DECLARE_CLASS
-+     * calls.
-+     */
++/* regular expression wrapper functions */
++extern void* apc_regex_compile_array(char* patterns[] TSRMLS_DC);
++extern void apc_regex_destroy_array(void* p);
++extern int apc_regex_match_array(void* p, const char* input);
 +
-+    if(cl.name_len != 0 && cl.name[0] == '\0') {
-+        if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) {
-+            return SUCCESS;
-+        }
-+    }
-+    
-+#ifdef ZEND_ENGINE_2    
-+    /*
-+     * XXX: We need to free this somewhere...
-+     */
-+    allocated_ce = apc_php_malloc(sizeof(zend_class_entry*));    
++/* apc_crc32: returns the CRC-32 checksum of the first len bytes in buf */
++extern unsigned int apc_crc32(const char* buf, int len);
 +
-+    if(!allocated_ce) {
-+        return FAILURE;
-+    }
++/* apc_flip_hash flips keys and values for faster searching */
++extern HashTable* apc_flip_hash(HashTable *hash); 
 +
-+    *allocated_ce = 
-+#endif        
-+    class_entry =
-+        apc_copy_class_entry_for_execution(cl.class_entry,
-+                                           cl.is_derived);
++#define APC_NEGATIVE_MATCH 1
++#define APC_POSITIVE_MATCH 2
 +
++#define apc_time() \
++    (APCG(use_request_time) ? sapi_get_request_time(TSRMLS_C) : time(0));
 +
-+    /* restore parent class pointer for compile-time inheritance */
-+    if (cl.parent_name != NULL) {
-+#ifdef ZEND_ENGINE_2    
-+        zend_class_entry** parent_ptr = NULL;
-+        /*
-+         * zend_lookup_class has to be due to presence of __autoload, 
-+         * just looking up the EG(class_table) is not enough in php5!
-+         * Even more dangerously, thanks to __autoload and people using
-+         * class names as filepaths for inclusion, this has to be case
-+         * sensitive. zend_lookup_class automatically does a case_fold
-+         * internally, but passes the case preserved version to __autoload.
-+         * Aside: Do NOT pass *strlen(cl.parent_name)+1* because 
-+         * zend_lookup_class does it internally anyway!
-+         */
-+        status = zend_lookup_class(cl.parent_name,
-+                                    strlen(cl.parent_name),
-+                                    &parent_ptr TSRMLS_CC);
-+#else
-+        status = zend_hash_find(EG(class_table),
-+                                cl.parent_name,
-+                                strlen(cl.parent_name)+1,
-+                                (void**) &parent);
-+#endif
-+        if (status == FAILURE) {
-+            if(APCG(report_autofilter)) {
-+                apc_wprint("Dynamic inheritance detected for class %s", cl.name);
-+            }
-+            class_entry->parent = NULL;
-+            return status;
-+        }
-+        else {
-+#ifdef ZEND_ENGINE_2            
-+            parent = *parent_ptr;
-+#endif 
-+            class_entry->parent = parent;
-+#ifdef ZEND_ENGINE_2
-+            zend_do_inheritance(class_entry, parent TSRMLS_CC);
-+#else
-+            zend_do_inheritance(class_entry, parent);
 +#endif
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_iterator.c php-5.3.1/ext/apc/apc_iterator.c
+--- php-5.3.1.orig/ext/apc/apc_iterator.c      1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_iterator.c   1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,634 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2008 The PHP Group                                     |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Brian Shire <shire@.php.net>                                |
++  +----------------------------------------------------------------------+
++
++ */
++
++/* $Id: apc_iterator.c 284698 2009-07-24 11:35:52Z kalle $ */
++
++#include "php_apc.h"
++#include "apc_iterator.h"
++#include "apc_cache.h"
++#include "apc_zend.h"
++
++#include "ext/standard/md5.h"
++
++#include "zend_interfaces.h"
++
++zend_class_entry *apc_iterator_ce;
++zend_object_handlers apc_iterator_object_handlers;
++
++
++/* {{{ apc_iterator_item */
++static apc_iterator_item_t* apc_iterator_item_ctor(apc_iterator_t *iterator, slot_t **slot_pp) {
++    zval *zvalue;
++    char md5str[33];
++    slot_t *slot = *slot_pp;
++    apc_context_t ctxt = {0, };
++    apc_iterator_item_t *item = ecalloc(1, sizeof(apc_iterator_item_t));
++
++    if (slot->key.type == APC_CACHE_KEY_FILE) {
++        /* keys should be unique and with stat=1 we could have multiple files with the same name, so use '<device> <inode>' instead */
++        item->key_len = spprintf(&item->key, 0, "%ld %ld", (ulong)slot->key.data.file.device, (ulong)slot->key.data.file.inode);
++        item->filename_key = estrdup(slot->value->data.file.filename);
++    } else if (slot->key.type == APC_CACHE_KEY_USER) {
++        item->key = estrndup((char*)slot->key.data.user.identifier, slot->key.data.user.identifier_len);
++        item->key_len = slot->key.data.user.identifier_len;
++        item->filename_key = item->key; 
++    } else if (slot->key.type == APC_CACHE_KEY_FPFILE) {
++        item->key = estrndup((char*)slot->key.data.fpfile.fullpath, slot->key.data.fpfile.fullpath_len);
++        item->key_len = slot->key.data.fpfile.fullpath_len;
++    } else {
++        apc_eprint("Internal error, invalid entry type.");
++    }
++
++    ALLOC_INIT_ZVAL(item->value);
++    array_init(item->value);
++
++    if (APC_ITER_TYPE & iterator->format) {
++        if(slot->value->type == APC_CACHE_ENTRY_FILE) {
++            add_assoc_string(item->value, "type", "file", 1);
++        } else if(slot->value->type == APC_CACHE_ENTRY_USER) {
++            add_assoc_string(item->value, "type", "user", 1);
++        }
++    }
++    if (APC_ITER_FILENAME & iterator->format) {
++        if(slot->value->type == APC_CACHE_ENTRY_FILE) {
++            if (slot->key.type == APC_CACHE_KEY_FILE) {
++              add_assoc_string(item->value, "filename", slot->value->data.file.filename, 1);
++            } else {  /* APC_CACHE_FPFILE */
++              add_assoc_string(item->value, "filename", (char*)slot->key.data.fpfile.fullpath, 1);
++            }
++        }
++    }
++    if (APC_ITER_DEVICE & iterator->format) {
++        if(slot->key.type == APC_CACHE_KEY_FILE) {
++            add_assoc_long(item->value, "device", slot->key.data.file.device);
++        }
++    }
++    if (APC_ITER_INODE & iterator->format) {
++        if(slot->key.type == APC_CACHE_KEY_FILE) {
++            add_assoc_long(item->value, "inode", slot->key.data.file.inode);
 +        }
++    }
++    if (APC_ITER_KEY & iterator->format) {
++        add_assoc_stringl(item->value, "key", item->key, item->key_len, 1);
++    }
++    if (APC_ITER_VALUE & iterator->format) {
++        if(slot->value->type == APC_CACHE_ENTRY_USER) {
 +
++            ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, NULL, NULL);
++            ctxt.copy = APC_COPY_OUT_USER;
 +
++            MAKE_STD_ZVAL(zvalue);
++            apc_cache_fetch_zval(zvalue, slot->value->data.user.val, &ctxt);
++            apc_pool_destroy(ctxt.pool);
++            add_assoc_zval(item->value, "value", zvalue);
++        }
++    }
++    if (APC_ITER_MD5 & iterator->format) {
++        if(slot->value->type == APC_CACHE_ENTRY_FILE) {
++            if(slot->key.md5) {
++                make_digest(md5str, slot->key.md5);
++                add_assoc_string(item->value, "md5", md5str, 1);
++            }
++        }
++    }
++    if (APC_ITER_NUM_HITS & iterator->format) {
++        add_assoc_long(item->value, "num_hits", slot->num_hits);
++    }
++    if (APC_ITER_MTIME & iterator->format) {
++        add_assoc_long(item->value, "mtime", slot->key.mtime);
++    }
++    if (APC_ITER_CTIME & iterator->format) {
++        add_assoc_long(item->value, "creation_time", slot->creation_time);
++    }
++    if (APC_ITER_DTIME & iterator->format) {
++        add_assoc_long(item->value, "deletion_time", slot->deletion_time);
++    }
++    if (APC_ITER_ATIME & iterator->format) {
++        add_assoc_long(item->value, "access_time", slot->access_time);
++    }
++    if (APC_ITER_REFCOUNT & iterator->format) {
++        add_assoc_long(item->value, "ref_count", slot->value->ref_count);
++    }
++    if (APC_ITER_MEM_SIZE & iterator->format) {
++        add_assoc_long(item->value, "mem_size", slot->value->mem_size);
++    }
++    if (APC_ITER_TTL & iterator->format) {
++        if(slot->value->type == APC_CACHE_ENTRY_USER) {
++            add_assoc_long(item->value, "ttl", slot->value->data.user.ttl);
++        }
 +    }
 +
-+#ifdef ZEND_ENGINE_2                           
-+    status = zend_hash_add(EG(class_table),
-+                           cl.name,
-+                           cl.name_len+1,
-+                           allocated_ce,
-+                           sizeof(zend_class_entry*),
-+                           NULL);
-+#else                           
-+    status = zend_hash_add(EG(class_table),
-+                           cl.name,
-+                           cl.name_len+1,
-+                           class_entry,
-+                           sizeof(zend_class_entry),
-+                           NULL);
-+#endif                           
++    return item;
++}
++/* }}} */
 +
-+    if (status == FAILURE) {
-+        apc_eprint("Cannot redeclare class %s", cl.name);
-+    } 
-+    return status;
++/* {{{ apc_iterator_clone */
++static zend_object_value apc_iterator_clone(zval *zobject TSRMLS_DC) {
++    zend_object_value value = {0};
++    apc_eprint("APCIterator object cannot be cloned.");
++    return value;
 +}
 +/* }}} */
 +
-+/* {{{ uninstall_class */
-+static int uninstall_class(apc_class_t cl TSRMLS_DC)
-+{
-+    int status;
++/* {{{ apc_iterator_item_dtor */
++static void apc_iterator_item_dtor(apc_iterator_item_t *item) {
++    if (item->filename_key && item->filename_key != item->key) {
++        efree(item->filename_key);
++    }
++    if (item->key) {
++        efree(item->key);
++    }
++    if (item->value) {
++        zval_ptr_dtor(&item->value);
++    }
++    efree(item);
++}
++/* }}} */
++
++/* {{{ apc_iterator_destroy */
++static void apc_iterator_destroy(void *object, zend_object_handle handle TSRMLS_DC) {
++    apc_iterator_t *iterator = (apc_iterator_t*)object;
++
++    if (iterator->initialized == 0) {
++        return;
++    }
++
++    while (apc_stack_size(iterator->stack) > 0) {
++        apc_iterator_item_dtor(apc_stack_pop(iterator->stack));
++    }
++    if (iterator->regex) {
++        efree(iterator->regex);
++    }
++    if (iterator->search_hash) {
++        zend_hash_destroy(iterator->search_hash);
++        efree(iterator->search_hash);
++    }
++    iterator->initialized = 0;
 +
-+#ifdef ZEND_ENGINE_2                           
-+    status = zend_hash_del(EG(class_table),
-+                           cl.name,
-+                           cl.name_len+1);
-+#else                           
-+    status = zend_hash_del(EG(class_table),
-+                           cl.name,
-+                           cl.name_len+1);
-+#endif                           
-+    if (status == FAILURE) {
-+        apc_eprint("Cannot delete class %s", cl.name);
-+    } 
-+    return status;
 +}
 +/* }}} */
 +
-+/* {{{ compare_file_handles */
-+static int compare_file_handles(void* a, void* b)
-+{
-+    zend_file_handle* fh1 = (zend_file_handle*)a;
-+    zend_file_handle* fh2 = (zend_file_handle*)b;
-+    return (fh1->type == fh2->type && 
-+            fh1->filename == fh2->filename &&
-+            fh1->opened_path == fh2->opened_path);
++/* {{{ acp_iterator_free */
++static void apc_iterator_free(void *object TSRMLS_DC) {
++    zend_object_std_dtor(object TSRMLS_CC);
++    efree(object);
 +}
 +/* }}} */
 +
-+/* {{{ cached_compile */
-+static zend_op_array* cached_compile(zend_file_handle* h,
-+                                        int type TSRMLS_DC)
-+{
-+    apc_cache_entry_t* cache_entry;
-+    int i, ii;
++/* {{{ apc_iterator_create */
++static zend_object_value apc_iterator_create(zend_class_entry *ce TSRMLS_DC) {
++    zend_object_value retval;
++    apc_iterator_t *iterator;
 +
-+    cache_entry = (apc_cache_entry_t*) apc_stack_top(APCG(cache_stack));
-+    assert(cache_entry != NULL);
++    iterator = emalloc(sizeof(apc_iterator_t));
++    iterator->obj.ce = ce;
++    ALLOC_HASHTABLE(iterator->obj.properties);
++    zend_hash_init(iterator->obj.properties, 0, NULL, ZVAL_PTR_DTOR, 0);
++    iterator->obj.guards = NULL;
++    iterator->initialized = 0;
++    retval.handle = zend_objects_store_put(iterator, apc_iterator_destroy, apc_iterator_free, NULL TSRMLS_CC);
++    retval.handlers = &apc_iterator_object_handlers;
 +
-+    if (cache_entry->data.file.classes) {
-+        for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
-+            if(install_class(cache_entry->data.file.classes[i] TSRMLS_CC) == FAILURE) {
-+                goto default_compile;
-+            }
-+        }
-+    }
++    return retval;
++}
++/* }}} */
 +
-+    if (cache_entry->data.file.functions) {
-+        for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
-+            install_function(cache_entry->data.file.functions[i] TSRMLS_CC);
++/* {{{ apc_iterator_search_match
++ *       Verify if the key matches oru search parameters
++ */
++static int apc_iterator_search_match(apc_iterator_t *iterator, slot_t **slot) {
++    char *key;
++    int key_len;
++    char *fname_key = NULL;
++    int fname_key_len;
++    int rval = 1;
++
++    if ((*slot)->key.type == APC_CACHE_KEY_FILE) {
++        key = estrdup((*slot)->value->data.file.filename);
++        key_len = strlen(key);
++        fname_key_len = spprintf(&fname_key, 0, "%ld %ld", (*slot)->key.data.file.device, (*slot)->key.data.file.inode);
++    } else if ((*slot)->key.type == APC_CACHE_KEY_USER) {
++        key = (char*)(*slot)->key.data.user.identifier;
++        key_len = (*slot)->key.data.user.identifier_len;
++    } else if ((*slot)->key.type == APC_CACHE_KEY_FPFILE) {
++        key = (char*)(*slot)->key.data.fpfile.fullpath;
++        key_len = (*slot)->key.data.fpfile.fullpath_len;
++    }
++
++#ifdef ITERATOR_PCRE
++    if (iterator->regex) {
++        rval = (pcre_exec(iterator->re, NULL, key, strlen(key), 0, 0, NULL, 0) >= 0);
++    }
++#endif
++            
++    if (iterator->search_hash) {
++        rval = zend_hash_exists(iterator->search_hash, key, key_len+1);
++        if (!rval && fname_key) {
++            rval = zend_hash_exists(iterator->search_hash, fname_key, fname_key_len+1);
 +        }
 +    }
 +
++    return rval;
++}
++/* }}} */
 +
-+    return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array TSRMLS_CC);
++/* {{{ apc_iterator_fetch_active */
++static int apc_iterator_fetch_active(apc_iterator_t *iterator) {
++    int count=0;
++    slot_t **slot;
++    apc_iterator_item_t *item;
++
++    while (apc_stack_size(iterator->stack) > 0) {
++        apc_iterator_item_dtor(apc_stack_pop(iterator->stack));
++    }
++
++    CACHE_LOCK(iterator->cache);
++    while(count <= iterator->chunk_size && iterator->slot_idx < iterator->cache->num_slots) {
++        slot = &iterator->cache->slots[iterator->slot_idx];
++        while(*slot) {
++            if (apc_iterator_search_match(iterator, slot)) {
++                count++;
++                item = apc_iterator_item_ctor(iterator, slot);
++                if (item) {
++                    apc_stack_push(iterator->stack, item);
++                }
++            }
++            slot = &(*slot)->next;
++        }
++        iterator->slot_idx++;
++    }
++    CACHE_UNLOCK(iterator->cache);
++    iterator->stack_idx = 0;
++    return count;
++}
++/* }}} */
 +
-+default_compile:
++/* {{{ apc_iterator_fetch_deleted */
++static int apc_iterator_fetch_deleted(apc_iterator_t *iterator) {
++    int count=0;
++    slot_t **slot;
++    apc_iterator_item_t *item;
 +
-+    if(APCG(report_autofilter)) {
-+        apc_wprint("Autofiltering %s", h->opened_path);
++    CACHE_LOCK(iterator->cache);
++    slot = &iterator->cache->header->deleted_list;
++    while ((*slot) && count <= iterator->slot_idx) {
++        count++;
++        slot = &(*slot)->next;
 +    }
-+
-+    if(cache_entry->data.file.classes) {
-+        for(ii = 0; ii < i ; ii++) {
-+            uninstall_class(cache_entry->data.file.classes[ii] TSRMLS_CC);
++    count = 0;
++    while ((*slot) && count < iterator->chunk_size) {
++        if (apc_iterator_search_match(iterator, slot)) {
++            count++;
++            item = apc_iterator_item_ctor(iterator, slot);
++            if (item) {
++                apc_stack_push(iterator->stack, item);
++            }
 +        }
++        slot = &(*slot)->next;
 +    }
-+    
-+    apc_stack_pop(APCG(cache_stack)); /* pop out cache_entry */
-+    
-+    apc_cache_release(apc_cache, cache_entry);
++    CACHE_UNLOCK(iterator->cache);
++    iterator->slot_idx += count;
++    iterator->stack_idx = 0;
++    return count;
++}
++/* }}} */
 +
-+    /* cannot free up cache data yet, it maybe in use */
-+    
-+    zend_llist_del_element(&CG(open_files), h, compare_file_handles); /* XXX: kludge */
-+    
-+    h->type = ZEND_HANDLE_FILENAME;
++/* {{{ apc_iterator_totals */
++static void apc_iterator_totals(apc_iterator_t *iterator) {
++    slot_t **slot;
++    int i;
 +
-+    return NULL;
++    CACHE_LOCK(iterator->cache);
++    for (i=0; i < iterator->cache->num_slots; i++) {
++        slot = &iterator->cache->slots[i];
++        while((*slot)) {
++            if (apc_iterator_search_match(iterator, slot)) {
++                iterator->size += (*slot)->value->mem_size;
++                iterator->hits += (*slot)->num_hits;
++                iterator->count++;
++            }
++            slot = &(*slot)->next;
++        }
++    }
++    CACHE_UNLOCK(iterator->cache);
++    iterator->totals_flag = 1;
 +}
 +/* }}} */
 +
-+/* {{{ my_compile_file
-+   Overrides zend_compile_file */
-+static zend_op_array* my_compile_file(zend_file_handle* h,
-+                                               int type TSRMLS_DC)
-+{
-+    apc_cache_key_t key;
-+    apc_cache_entry_t* cache_entry;
-+    zend_op_array* op_array;
-+    int num_functions, num_classes, ret;
-+    zend_op_array* alloc_op_array;
-+    apc_function_t* alloc_functions;
-+    apc_class_t* alloc_classes;
-+    time_t t;
-+    char *path;
-+    size_t mem_size;
++/* {{{ proto object APCIterator::__costruct(string cache [, mixed search [, long format [, long chunk_size [, long list ]]]]) */
++PHP_METHOD(apc_iterator, __construct) {
++    zval *object = getThis();
++    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(object TSRMLS_CC);
++    char *cachetype;
++    int cachetype_len;
++    long format = APC_ITER_ALL;
++    long chunk_size=0;
++    zval *search = NULL;
++    long list = APC_LIST_ACTIVE;
++
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|zlll", &cachetype, &cachetype_len, &search, &format, &chunk_size, &list) == FAILURE) {
++        return;
++    }
 +
-+    if (!APCG(enabled) || (apc_cache_busy(apc_cache) && !APCG(localcache))) {
-+              return old_compile_file(h, type TSRMLS_CC);
-+      }
++    if (chunk_size < 0) {
++        apc_eprint("APCIterator chunk size must be greater than 0.");
++        return;
++    }
 +
-+    /* check our regular expression filters */
-+    if (APCG(filters) && apc_compiled_filters) {
-+        int ret = apc_regex_match_array(apc_compiled_filters, h->filename);
-+        if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) {
-+            return old_compile_file(h, type TSRMLS_CC);
-+        }
-+    } else if(!APCG(cache_by_default)) {
-+        return old_compile_file(h, type TSRMLS_CC);
++    if (format > APC_ITER_ALL) {
++        apc_eprint("APCIterator format is invalid.");
++        return;
 +    }
 +
-+#if PHP_API_VERSION < 20041225
-+#if HAVE_APACHE && defined(APC_PHP4_STAT)
-+    t = ((request_rec *)SG(server_context))->request_time;
-+#else 
-+    t = time(0);
-+#endif
-+#else 
-+    t = sapi_get_request_time(TSRMLS_C);
-+#endif
++    if (list == APC_LIST_ACTIVE) {
++        iterator->fetch = apc_iterator_fetch_active;
++    } else if (list == APC_LIST_DELETED) {
++        iterator->fetch = apc_iterator_fetch_deleted;
++    } else {
++        apc_wprint("APCIterator invalid list type.");
++        return;
++    }
 +
-+#ifdef __DEBUG_APC__
-+    fprintf(stderr,"1. h->opened_path=[%s]  h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
++    if(!strcasecmp(cachetype,"user")) {
++        iterator->cache = apc_user_cache;
++    } else {
++        iterator->cache = apc_cache;
++    }
++
++    iterator->slot_idx = 0;
++    iterator->stack_idx = 0;
++    iterator->key_idx = 0;
++    iterator->chunk_size = chunk_size == 0 ? APC_DEFAULT_CHUNK_SIZE : chunk_size;
++    iterator->stack = apc_stack_create(chunk_size);
++    iterator->format = format;
++    iterator->totals_flag = 0;
++    iterator->count = 0;
++    iterator->size = 0;
++    iterator->hits = 0;
++    iterator->regex = NULL;
++    iterator->regex_len = 0;
++    iterator->search_hash = NULL;
++    if (search && Z_TYPE_P(search) == IS_STRING && Z_STRLEN_P(search)) {
++#ifdef ITERATOR_PCRE
++        iterator->regex = estrndup(Z_STRVAL_P(search), Z_STRLEN_P(search));
++        iterator->regex_len = Z_STRLEN_P(search);
++        iterator->re = pcre_get_compiled_regex(Z_STRVAL_P(search), NULL, NULL TSRMLS_CC);
++
++        if(!iterator->re) {
++            apc_eprint("Could not compile regular expression: %s", Z_STRVAL_P(search));
++        }
++#else
++        apc_eprint("Regular expressions support is not enabled, please enable PCRE for APCIterator regex support");
 +#endif
++    } else if (search && Z_TYPE_P(search) == IS_ARRAY) {
++        Z_ADDREF_P(search);
++        iterator->search_hash = apc_flip_hash(Z_ARRVAL_P(search));
++    }
++    iterator->initialized = 1;
++}
++/* }}} */
 +
-+    /* try to create a cache key; if we fail, give up on caching */
-+    if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) {
-+        return old_compile_file(h, type TSRMLS_CC);
++/* {{{ proto APCIterator::rewind() */
++PHP_METHOD(apc_iterator, rewind) {
++    zval *object = getThis();
++    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(object TSRMLS_CC);
++
++    if (iterator->initialized == 0) {
++        RETURN_FALSE;
 +    }
 +
++    iterator->slot_idx = 0;
++    iterator->stack_idx = 0;
++    iterator->key_idx = 0;
++    iterator->fetch(iterator);
++}
++/* }}} */
 +
-+    if(!APCG(force_file_update)) {
-+        if(APCG(localcache)) {
-+            /* search for the file in the local cache */
-+            cache_entry = apc_local_cache_find(APCG(lcache), key, t);
-+        } else {
-+            /* search for the file in the cache */
-+            cache_entry = apc_cache_find(apc_cache, key, t);
-+        }
-+    } else {
-+        cache_entry = NULL;
++/* {{{ proto boolean APCIterator::valid() */
++PHP_METHOD(apc_iterator, valid) {
++    zval *object = getThis();
++    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(object TSRMLS_CC);
++
++    if (iterator->initialized == 0) {
++        RETURN_FALSE;
 +    }
 +
-+    if (cache_entry != NULL) {
-+        int dummy = 1;
-+        if (h->opened_path == NULL) {
-+            h->opened_path = estrdup(cache_entry->data.file.filename);
-+        }
-+        zend_hash_add(&EG(included_files), h->opened_path, strlen(h->opened_path)+1, (void *)&dummy, sizeof(int), NULL);
-+        zend_llist_add_element(&CG(open_files), h); /* XXX kludge */
-+        apc_stack_push(APCG(cache_stack), cache_entry);
-+        op_array = cached_compile(h, type TSRMLS_CC);
-+        if(op_array) {
-+#ifdef APC_FILEHITS
-+            /* If the file comes from the cache, add it to the global request file list */
-+            add_next_index_string(APCG(filehits), h->filename, 1);
-+#endif
-+            return op_array;
-+        }
-+        if(APCG(report_autofilter)) {
-+            apc_wprint("Recompiling %s", h->opened_path);
-+        }
-+        /* TODO: check what happens with EG(included_files) */
++    if (apc_stack_size(iterator->stack) == iterator->stack_idx) {
++        iterator->fetch(iterator);
 +    }
-+    
-+    if(apc_cache_busy(apc_cache) && APCG(localcache)) {
-+        /* possibly local cache returned NULL because cache is busy */
-+              return old_compile_file(h, type TSRMLS_CC);
-+      }
 +
-+    /* remember how many functions and classes existed before compilation */
-+    num_functions = zend_hash_num_elements(CG(function_table));
-+    num_classes   = zend_hash_num_elements(CG(class_table));
-+    
-+    /* compile the file using the default compile function */
-+    op_array = old_compile_file(h, type TSRMLS_CC);
-+    if (op_array == NULL) {
-+        return NULL;
++    RETURN_BOOL(apc_stack_size(iterator->stack) == 0 ? 0 : 1);
++}
++/* }}} */
++
++/* {{{ proto mixed APCIterator::current() */
++PHP_METHOD(apc_iterator, current) {
++    zval *object = getThis();
++    apc_iterator_item_t *item;
++    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(object TSRMLS_CC);
++    if (iterator->initialized == 0) {
++        RETURN_FALSE;
 +    }
-+    /*
-+     * Basically this will cause a file only to be cached on a percentage 
-+     * of the attempts.  This is to avoid cache slams when starting up a
-+     * very busy server or when modifying files on a very busy live server.
-+     * There is no point having many processes all trying to cache the same
-+     * file at the same time.  By introducing a chance of being cached
-+     * we theoretically cut the cache slam problem by the given percentage.
-+     * For example if apc.slam_defense is set to 66 then 2/3 of the attempts
-+     * to cache an uncached file will be ignored.
-+     */
-+    if(APCG(slam_defense)) {
-+        if(APCG(slam_rand)==-1) {
-+            APCG(slam_rand) = (int)(100.0*rand()/(RAND_MAX+1.0));
-+        }
-+        if(APCG(slam_rand) < APCG(slam_defense)) {
-+            return op_array;
++    if (apc_stack_size(iterator->stack) == iterator->stack_idx) {
++        if (iterator->fetch(iterator) == 0) {
++            RETURN_FALSE;
 +        }
 +    }
++    item = apc_stack_get(iterator->stack, iterator->stack_idx);
++    RETURN_ZVAL(item->value, 1, 0);
++}
++/* }}} */
 +
-+    /* Make sure the mtime reflects the files last known mtime in the case of fpstat==0 */
-+    if(key.type == APC_CACHE_KEY_FPFILE) {
-+        apc_fileinfo_t fileinfo;
-+        struct stat *tmp_buf = NULL;
-+        if(!strcmp(SG(request_info).path_translated, h->filename)) {
-+            tmp_buf = sapi_get_stat(TSRMLS_C);  /* Apache has already done this stat() for us */
-+        }
-+        if(tmp_buf) { 
-+            fileinfo.st_buf = *tmp_buf;
-+        } else {
-+            if (apc_search_paths(h->filename, PG(include_path), &fileinfo) != 0) {
-+#ifdef __DEBUG_APC__
-+                fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",filename,SG(request_info).path_translated);
-+#endif
-+                return op_array;
-+            }
-+        }
-+        key.mtime = fileinfo.st_buf.st_mtime;
-+    }
-+
-+    HANDLE_BLOCK_INTERRUPTIONS();
-+
-+#if NONBLOCKING_LOCK_AVAILABLE
-+    if(APCG(write_lock)) {
-+        if(!apc_cache_write_lock(apc_cache)) {
-+            HANDLE_UNBLOCK_INTERRUPTIONS();
-+            return op_array;
-+        }
-+    }
-+#endif
-+
-+    mem_size = 0;
-+    APCG(mem_size_ptr) = &mem_size;
-+    if(!(alloc_op_array = apc_copy_op_array(NULL, op_array, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
-+        apc_cache_expunge(apc_cache,t);
-+        apc_cache_expunge(apc_user_cache,t);
-+        APCG(mem_size_ptr) = NULL;
-+#if NONBLOCKING_LOCK_AVAILABLE
-+        if(APCG(write_lock)) {
-+            apc_cache_write_unlock(apc_cache);
-+        }
-+#endif
-+        HANDLE_UNBLOCK_INTERRUPTIONS();
-+        return op_array;
-+    }
-+    
-+    if(!(alloc_functions = apc_copy_new_functions(num_functions, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
-+        apc_free_op_array(alloc_op_array, apc_sma_free);
-+        apc_cache_expunge(apc_cache,t);
-+        apc_cache_expunge(apc_user_cache,t);
-+        APCG(mem_size_ptr) = NULL;
-+#if NONBLOCKING_LOCK_AVAILABLE
-+        if(APCG(write_lock)) {
-+            apc_cache_write_unlock(apc_cache);
-+        }
-+#endif
-+        HANDLE_UNBLOCK_INTERRUPTIONS();
-+        return op_array;
-+    }
-+    if(!(alloc_classes = apc_copy_new_classes(op_array, num_classes, apc_sma_malloc, apc_sma_free TSRMLS_CC))) {
-+        apc_free_op_array(alloc_op_array, apc_sma_free);
-+        apc_free_functions(alloc_functions, apc_sma_free);
-+        apc_cache_expunge(apc_cache,t);
-+        apc_cache_expunge(apc_user_cache,t);
-+        APCG(mem_size_ptr) = NULL;
-+#if NONBLOCKING_LOCK_AVAILABLE
-+        if(APCG(write_lock)) {
-+            apc_cache_write_unlock(apc_cache);
-+        }
-+#endif
-+        HANDLE_UNBLOCK_INTERRUPTIONS();
-+        return op_array;
++/* {{{ proto string APCIterator::key() */
++PHP_METHOD(apc_iterator, key) {
++    zval *object = getThis();
++    apc_iterator_item_t *item;
++    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(object TSRMLS_CC);
++    if (iterator->initialized == 0 || apc_stack_size(iterator->stack) == 0) {
++        RETURN_FALSE;
 +    }
-+
-+    path = h->opened_path;
-+    if(!path) path=h->filename;
-+
-+#ifdef __DEBUG_APC__
-+    fprintf(stderr,"2. h->opened_path=[%s]  h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
-+#endif
-+
-+    if(!(cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes))) {
-+        apc_free_op_array(alloc_op_array, apc_sma_free);
-+        apc_free_functions(alloc_functions, apc_sma_free);
-+        apc_free_classes(alloc_classes, apc_sma_free);
-+        apc_cache_expunge(apc_cache,t);
-+        apc_cache_expunge(apc_user_cache,t);
-+        APCG(mem_size_ptr) = NULL;
-+#if NONBLOCKING_LOCK_AVAILABLE
-+        if(APCG(write_lock)) {
-+            apc_cache_write_unlock(apc_cache);
++    if (apc_stack_size(iterator->stack) == iterator->stack_idx) {
++        if (iterator->fetch(iterator) == 0) {
++            RETURN_FALSE;
 +        }
-+#endif
-+        HANDLE_UNBLOCK_INTERRUPTIONS();
-+        return op_array;
 +    }
-+    APCG(mem_size_ptr) = NULL;
-+    cache_entry->mem_size = mem_size;
-+
-+    if ((ret = apc_cache_insert(apc_cache, key, cache_entry, t)) != 1) {
-+        apc_cache_free_entry(cache_entry);
-+        if(ret==-1) {
-+            apc_cache_expunge(apc_cache,t);
-+            apc_cache_expunge(apc_user_cache,t);
-+        }
++    item = apc_stack_get(iterator->stack, iterator->stack_idx);
++    if (item->key) {
++        RETURN_STRINGL(item->key, item->key_len, 1);
++    } else {
++        RETURN_LONG(iterator->key_idx);
 +    }
++}
++/* }}} */
 +
-+#if NONBLOCKING_LOCK_AVAILABLE
-+    if(APCG(write_lock)) {
-+        apc_cache_write_unlock(apc_cache);
++/* {{{ proto APCIterator::next() */
++PHP_METHOD(apc_iterator, next) {
++    zval *object = getThis();
++    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(object TSRMLS_CC);
++    if (iterator->initialized == 0 || apc_stack_size(iterator->stack) == 0) {
++        RETURN_FALSE;
 +    }
-+#endif
-+    HANDLE_UNBLOCK_INTERRUPTIONS();
-+
-+    return op_array;
++    iterator->stack_idx++;
++    iterator->key_idx++;
++    RETURN_TRUE;
 +}
 +/* }}} */
 +
-+/* {{{ module init and shutdown */
-+
-+int apc_module_init(int module_number TSRMLS_DC)
-+{
-+    /* apc initialization */
-+#if APC_MMAP
-+    apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, APCG(mmap_file_mask));
-+#else
-+    apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, NULL);
-+#endif
-+    apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl));
-+    apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl));
++/* {{{ proto long APCIterator::getTotalHits() */
++PHP_METHOD(apc_iterator, getTotalHits) {
++    zval *object = getThis();
++    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(object TSRMLS_CC);
 +
-+    apc_compiled_filters = apc_regex_compile_array(APCG(filters));
++    if (iterator->initialized == 0) {
++        RETURN_FALSE;
++    }
 +
-+    /* override compilation */
-+    old_compile_file = zend_compile_file;
-+    zend_compile_file = my_compile_file;
-+    REGISTER_LONG_CONSTANT("\000apc_magic", (long)&set_compile_hook, CONST_PERSISTENT | CONST_CS);
++    if (iterator->totals_flag == 0) {
++        apc_iterator_totals(iterator);
++    }
 +
-+    APCG(initialized) = 1;
-+    return 0;
++    RETURN_LONG(iterator->hits);
 +}
++/* }}} */
 +
-+int apc_module_shutdown(TSRMLS_D)
-+{
-+    if (!APCG(initialized))
-+        return 0;
-+
-+    /* restore compilation */
-+    zend_compile_file = old_compile_file;
++/* {{{ proto long APCIterator:;getTotalSize() */
++PHP_METHOD(apc_iterator, getTotalSize) {
++    zval *object = getThis();
++    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(object TSRMLS_CC);
 +
-+    /* 
-+     * In case we got interrupted by a SIGTERM or something else during execution
-+     * we may have cache entries left on the stack that we need to check to make
-+     * sure that any functions or classes these may have added to the global function
-+     * and class tables are removed before we blow away the memory that hold them.
-+     * 
-+     * This is merely to remove memory leak warnings - as the process is terminated
-+     * immediately after shutdown. The following while loop can be removed without
-+     * affecting anything else.
-+     */
-+    while (apc_stack_size(APCG(cache_stack)) > 0) {
-+        int i;
-+        apc_cache_entry_t* cache_entry = (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
-+        if (cache_entry->data.file.functions) {
-+            for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
-+                zend_hash_del(EG(function_table),
-+                    cache_entry->data.file.functions[i].name,
-+                    cache_entry->data.file.functions[i].name_len+1);
-+            }
-+        }
-+        if (cache_entry->data.file.classes) {
-+            for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
-+                zend_hash_del(EG(class_table),
-+                    cache_entry->data.file.classes[i].name,
-+                    cache_entry->data.file.classes[i].name_len+1);
-+            }
-+        }
-+        apc_cache_release(apc_cache, cache_entry);
++    if (iterator->initialized == 0) {
++        RETURN_FALSE;
 +    }
 +
-+    apc_cache_destroy(apc_cache);
-+    apc_cache_destroy(apc_user_cache);
-+    apc_sma_cleanup();
++    if (iterator->totals_flag == 0) {
++        apc_iterator_totals(iterator);
++    }
 +
-+    APCG(initialized) = 0;
-+    return 0;
++    RETURN_LONG(iterator->size);
 +}
-+
 +/* }}} */
 +
-+/* {{{ process init and shutdown */
-+int apc_process_init(int module_number TSRMLS_DC)
-+{
-+    int minttl = (APCG(gc_ttl) >  APCG(ttl) ? APCG(ttl) : APCG(gc_ttl))/2;
-+    int size = APCG(localcache_size);
-+    if(APCG(initialized) && APCG(localcache)) {
-+        /* TTL is 2 mins by default */
-+        APCG(lcache) = apc_local_cache_create(apc_cache, size, minttl ? minttl : 120); 
++/* {{{ proto long APCIterator::getTotalCount() */
++PHP_METHOD(apc_iterator, getTotalCount) {
++    zval *object = getThis();
++    apc_iterator_t *iterator = (apc_iterator_t*)zend_object_store_get_object(object TSRMLS_CC);
++
++    if (iterator->initialized == 0) {
++        RETURN_FALSE;
 +    }
-+    return 0;
-+}
 +
-+int apc_process_shutdown(TSRMLS_D)
-+{
-+    if(APCG(initialized) && APCG(localcache) && APCG(lcache)) {
-+        apc_local_cache_destroy(APCG(lcache));
-+        APCG(lcache) = NULL;
++    if (iterator->totals_flag == 0) {
++        apc_iterator_totals(iterator);
 +    }
-+      return 0;
++
++    RETURN_LONG(iterator->count);
 +}
 +/* }}} */
 +
-+/* {{{ request init and shutdown */
-+
-+int apc_request_init(TSRMLS_D)
-+{
-+    apc_stack_clear(APCG(cache_stack));
-+    APCG(slam_rand) = -1;
-+    APCG(copied_zvals) = NULL;
++/* {{{ apc_iterator_functions */
++static function_entry apc_iterator_functions[] = {
++    PHP_ME(apc_iterator, __construct, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_CTOR)
++    PHP_ME(apc_iterator, rewind, NULL, ZEND_ACC_PUBLIC)
++    PHP_ME(apc_iterator, current, NULL, ZEND_ACC_PUBLIC)
++    PHP_ME(apc_iterator, key, NULL, ZEND_ACC_PUBLIC)
++    PHP_ME(apc_iterator, next, NULL, ZEND_ACC_PUBLIC)
++    PHP_ME(apc_iterator, valid, NULL, ZEND_ACC_PUBLIC)
++    PHP_ME(apc_iterator, getTotalHits, NULL, ZEND_ACC_PUBLIC)
++    PHP_ME(apc_iterator, getTotalSize, NULL, ZEND_ACC_PUBLIC)
++    PHP_ME(apc_iterator, getTotalCount, NULL, ZEND_ACC_PUBLIC)
++    {NULL, NULL, NULL}
++};
++/* }}} */
 +
-+#ifdef APC_FILEHITS
-+    ALLOC_INIT_ZVAL(APCG(filehits));
-+    array_init(APCG(filehits));
-+#endif
++/* {{{ apc_iterator_init */
++int apc_iterator_init(int module_number TSRMLS_DC) {
++    zend_class_entry ce;
++
++    INIT_CLASS_ENTRY(ce, APC_ITERATOR_NAME, apc_iterator_functions);
++    apc_iterator_ce = zend_register_internal_class(&ce TSRMLS_CC);
++    apc_iterator_ce->create_object = apc_iterator_create;
++    zend_class_implements(apc_iterator_ce TSRMLS_CC, 1, zend_ce_iterator);
++
++    zend_register_long_constant("APC_LIST_ACTIVE", sizeof("APC_LIST_ACTIVE"), APC_LIST_ACTIVE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_LIST_DELETED", sizeof("APC_LIST_DELETED"), APC_LIST_DELETED, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++
++    zend_register_long_constant("APC_ITER_TYPE", sizeof("APC_ITER_TYPE"), APC_ITER_TYPE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_KEY", sizeof("APC_ITER_KEY"), APC_ITER_KEY, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_FILENAME", sizeof("APC_ITER_FILENAME"), APC_ITER_FILENAME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_DEVICE", sizeof("APC_ITER_DEVICE"), APC_ITER_DEVICE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_INODE", sizeof("APC_ITER_INODE"), APC_ITER_INODE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_VALUE", sizeof("APC_ITER_VALUE"), APC_ITER_VALUE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_MD5", sizeof("APC_ITER_MD5"), APC_ITER_MD5, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_NUM_HITS", sizeof("APC_ITER_NUM_HITS"), APC_ITER_NUM_HITS, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_MTIME", sizeof("APC_ITER_MTIME"), APC_ITER_MTIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_CTIME", sizeof("APC_ITER_CTIME"), APC_ITER_CTIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_DTIME", sizeof("APC_ITER_DTIME"), APC_ITER_DTIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_ATIME", sizeof("APC_ITER_ATIME"), APC_ITER_ATIME, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_REFCOUNT", sizeof("APC_ITER_REFCOUNT"), APC_ITER_REFCOUNT, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_MEM_SIZE", sizeof("APC_ITER_MEM_SIZE"), APC_ITER_MEM_SIZE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_TTL", sizeof("APC_ITER_TTL"), APC_ITER_TTL, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_NONE", sizeof("APC_ITER_NONE"), APC_ITER_NONE, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++    zend_register_long_constant("APC_ITER_ALL", sizeof("APC_ITER_ALL"), APC_ITER_ALL, CONST_PERSISTENT | CONST_CS, module_number TSRMLS_CC);
++
++    memcpy(&apc_iterator_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
++    apc_iterator_object_handlers.clone_obj = apc_iterator_clone;
 +
-+    return 0;
++    return SUCCESS;
 +}
++/* }}} */
 +
-+int apc_request_shutdown(TSRMLS_D)
-+{
-+    apc_deactivate(TSRMLS_C);
-+
-+#ifdef APC_FILEHITS
-+    zval_ptr_dtor(&APCG(filehits));
-+#endif
-+
-+    return 0;
-+}
 +
-+/* }}} */
++int apc_iterator_delete(zval *zobj TSRMLS_DC) {
++    apc_iterator_t *iterator;
++    zend_class_entry *ce = Z_OBJCE_P(zobj);
++    apc_iterator_item_t *item;
 +
-+/* {{{ apc_deactivate */
-+void apc_deactivate(TSRMLS_D)
-+{
-+    /* The execution stack was unwound, which prevented us from decrementing
-+     * the reference counts on active cache entries in `my_execute`.
-+     */
-+    while (apc_stack_size(APCG(cache_stack)) > 0) {
-+        int i;
-+        zend_class_entry* zce = NULL;
-+        void ** centry = (void*)(&zce);
-+#ifdef ZEND_ENGINE_2
-+        zend_class_entry** pzce = NULL;
-+#endif
-+        
-+        apc_cache_entry_t* cache_entry =
-+            (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
++    if (!ce || !instanceof_function(ce, apc_iterator_ce TSRMLS_CC)) {
++        apc_eprint("apc_delete object argument must be instance of APCIterator");
++        return 0;
++    }
++    iterator = (apc_iterator_t*)zend_object_store_get_object(zobj TSRMLS_CC);
 +
-+        if (cache_entry->data.file.classes) {
-+            for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
-+#ifdef ZEND_ENGINE_2
-+                centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */
-+#endif
-+                if(zend_hash_find(EG(class_table), 
-+                    cache_entry->data.file.classes[i].name,
-+                    cache_entry->data.file.classes[i].name_len+1,
-+                    (void**)centry) == FAILURE)
-+                {
-+                    /* double inclusion of conditional classes ends up failing 
-+                     * this lookup the second time around.
-+                     */
-+                    continue;
-+                }
++    if (iterator->initialized == 0) {
++        return 0;
++    }
 +
-+#ifdef ZEND_ENGINE_2
-+                zce = *pzce;
-+#endif
-+                zend_hash_del(EG(class_table),
-+                    cache_entry->data.file.classes[i].name,
-+                    cache_entry->data.file.classes[i].name_len+1);
-+                
-+                apc_free_class_entry_after_execution(zce);
++    while (iterator->fetch(iterator)) {
++        while (iterator->stack_idx < apc_stack_size(iterator->stack)) {
++            item = apc_stack_get(iterator->stack, iterator->stack_idx++);
++            if (iterator->cache == apc_cache) {
++                apc_cache_delete(apc_cache, item->filename_key, strlen(item->filename_key)+1);
++            } else {
++                apc_cache_user_delete(apc_user_cache, item->key, item->key_len+1);
 +            }
 +        }
-+        apc_cache_release(apc_cache, cache_entry);
-+    }
-+    if(APCG(localcache)) {
-+        apc_local_cache_cleanup(APCG(lcache)); 
 +    }
++
++    return 1;
 +}
-+/* }}} */
++
 +
 +/*
 + * Local variables:
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_main.h php-5.2.5/ext/apc/apc_main.h
---- php-5.2.5-orig/ext/apc/apc_main.h  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_main.h       2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,67 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_iterator.h php-5.3.1/ext/apc/apc_iterator.h
+--- php-5.3.1.orig/ext/apc/apc_iterator.h      1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_iterator.h   1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,117 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2008 The PHP Group                                     |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -6728,48 +6660,98 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_main.h php-5.2.5/ext/apc/apc_main.h
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          George Schlossnagle <george@omniti.com>                     |
-+  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
-+  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
++  | Authors: Brian Shire <shire@.php.net>                                |
 +  +----------------------------------------------------------------------+
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++ */
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++/* $Id: apc_iterator.h 277132 2009-03-14 01:50:57Z shire $ */
 +
-+ */
++#ifndef APC_ITERATOR_H
++#define APC_ITERATOR_H
 +
-+/* $Id: apc_main.h,v 3.9 2007/02/28 01:15:18 gopalv Exp $ */
++#include "apc.h"
++#include "apc_stack.h"
 +
-+#ifndef APC_MAIN_H
-+#define APC_MAIN_H
++#if HAVE_PCRE || HAVE_BUNDLED_PCRE
++/*  Deal with problem present until php-5.2.2 where php_pcre.h was not installed correctly */
++#   if !HAVE_BUNDLED_PCRE && PHP_MAJOR_VERSION == 5 && (PHP_MINOR_VERSION < 2 || (PHP_MINOR_VERSION == 2 && PHP_RELEASE_VERSION < 2))
++#       include "apc_php_pcre.h"
++#   else
++#       include "ext/pcre/php_pcre.h"
++#   endif
++#   include "ext/standard/php_smart_str.h"
++#   define ITERATOR_PCRE 1
++#endif
 +
-+/*
-+ * This module provides the primary interface between PHP and APC.
-+ */
 +
-+extern int apc_module_init(int module_number TSRMLS_DC);
-+extern int apc_module_shutdown(TSRMLS_D);
-+extern int apc_process_init(int module_number TSRMLS_DC);
-+extern int apc_process_shutdown(TSRMLS_D);
-+extern int apc_request_init(TSRMLS_D);
-+extern int apc_request_shutdown(TSRMLS_D);
++#define APC_ITERATOR_NAME "APCIterator"
++
++#define APC_DEFAULT_CHUNK_SIZE 100
++
++#define APC_LIST_ACTIVE   0x1
++#define APC_LIST_DELETED  0x2
++
++#define APC_ITER_TYPE       (1L << 0) 
++#define APC_ITER_KEY        (1L << 1) 
++#define APC_ITER_FILENAME   (1L << 2) 
++#define APC_ITER_DEVICE     (1L << 3) 
++#define APC_ITER_INODE      (1L << 4) 
++#define APC_ITER_VALUE      (1L << 5) 
++#define APC_ITER_MD5        (1L << 6) 
++#define APC_ITER_NUM_HITS   (1L << 7) 
++#define APC_ITER_MTIME      (1L << 8) 
++#define APC_ITER_CTIME      (1L << 9) 
++#define APC_ITER_DTIME      (1L << 10) 
++#define APC_ITER_ATIME      (1L << 11) 
++#define APC_ITER_REFCOUNT   (1L << 12) 
++#define APC_ITER_MEM_SIZE   (1L << 13) 
++#define APC_ITER_TTL        (1L << 14)
++
++#define APC_ITER_NONE       (0x00000000L)
++#define APC_ITER_ALL        (0xffffffffL)
++
++typedef void* (*apc_iterator_item_cb_t)(slot_t **slot);
++
++
++/* {{{ apc_iterator_t */
++typedef struct _apc_iterator_t {
++    zend_object obj;         /* must always be first */
++    short int initialized;   /* sanity check in case __construct failed */
++    long format;             /* format bitmask of the return values ie: key, value, info */
++    int (*fetch)(struct _apc_iterator_t *iterator);
++                             /* fetch callback to fetch items from cache slots or lists */
++    apc_cache_t *cache;      /* cache which we are iterating on */
++    long slot_idx;           /* index to the slot array or linked list */
++    long chunk_size;         /* number of entries to pull down per fetch */
++    apc_stack_t *stack;      /* stack of entries pulled from cache */
++    int stack_idx;           /* index into the current stack */
++#ifdef ITERATOR_PCRE
++    pcre *re;                /* regex filter on entry identifiers */
++#endif
++    char *regex;             /* original regex expression or NULL */
++    int regex_len;           /* regex length */
++    HashTable *search_hash;  /* hash of keys to iterate over */
++    long key_idx;            /* incrementing index for numerical keys */
++    short int totals_flag;   /* flag if totals have been calculated */
++    long hits;               /* hit total */
++    size_t size;             /* size total */
++    long count;              /* count total */
++} apc_iterator_t;
++/* }}} */
 +
-+/*
-+ * apc_deactivate is called by the PHP interpreter when an "exception" is
-+ * raised (e.g., a call to the exit function) that unwinds the execution
-+ * stack.
-+ */
-+extern void apc_deactivate();
++/* {{{ apc_iterator_item */
++typedef struct _apc_iterator_item_t {
++    char *key;              /* string key */
++    long key_len;           /* strlen of key */
++    char *filename_key;     /* filename key used for deletion */
++    zval *value;
++} apc_iterator_item_t;
++/* }}} */
 +
 +
-+extern const char* apc_version();
++extern int apc_iterator_init(int module_number TSRMLS_DC);
++extern int apc_iterator_delete(zval *zobj TSRMLS_DC);
 +
 +#endif
 +
@@ -6778,18 +6760,18 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_main.h php-5.2.5/ext/apc/apc_main.h
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_mmap.c php-5.2.5/ext/apc/apc_mmap.c
---- php-5.2.5-orig/ext/apc/apc_mmap.c  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_mmap.c       2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,139 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_lock.h php-5.3.1/ext/apc/apc_lock.h
+--- php-5.3.1.orig/ext/apc/apc_lock.h  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_lock.h       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,100 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -6799,7 +6781,8 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_mmap.c php-5.2.5/ext/apc/apc_mmap.c
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
++  | Authors: George Schlossnagle <george@omniti.com>                     |
++  |          Rasmus Lerdorf <rasmus@php.net>                             |
 +  +----------------------------------------------------------------------+
 +
 +   This software was contributed to PHP by Community Connect Inc. in 2002
@@ -6812,128 +6795,87 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_mmap.c php-5.2.5/ext/apc/apc_mmap.c
 +
 + */
 +
-+/* $Id: apc_mmap.c,v 3.7 2007/12/20 23:00:51 shire Exp $ */
-+
-+#include "apc.h"
++/* $Id: apc_lock.h 268620 2008-11-09 02:30:49Z shire $ */
 +
-+#if APC_MMAP
++#ifndef APC_LOCK
++#define APC_LOCK
 +
-+#include <fcntl.h>
-+#include <sys/types.h>
-+#include <sys/mman.h>
-+
-+/* 
-+ * Some operating systems (like FreeBSD) have a MAP_NOSYNC flag that
-+ * tells whatever update daemons might be running to not flush dirty
-+ * vm pages to disk unless absolutely necessary.  My guess is that
-+ * most systems that don't have this probably default to only synching
-+ * to disk when absolutely necessary.
-+ */
-+#ifndef MAP_NOSYNC
-+#define MAP_NOSYNC 0
++#include "apc_sem.h"
++#include "apc_fcntl.h"
++#include "apc_pthreadmutex.h"
++#include "apc_spin.h"
++#ifdef HAVE_CONFIG_H
++#include <config.h>
 +#endif
 +
-+void *apc_mmap(char *file_mask, size_t size)
-+{
-+    void* shmaddr;  /* the shared memory address */
-+
-+    /* If no filename was provided, do an anonymous mmap */
-+    if(!file_mask || (file_mask && !strlen(file_mask))) {
-+        shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
-+    } else {
-+        int fd;
-+
-+        /* 
-+         * If the filemask contains .shm we try to do a POSIX-compliant shared memory
-+         * backed mmap which should avoid synchs on some platforms.  At least on
-+         * FreeBSD this implies MAP_NOSYNC and on Linux it is equivalent of mmap'ing
-+         * a file in a mounted shmfs.  For this to work on Linux you need to make sure
-+         * you actually have shmfs mounted.  Also on Linux, make sure the file_mask you
-+         * pass in has a leading / and no other /'s.  eg.  /apc.shm.XXXXXX
-+         * On FreeBSD these are mapped onto the regular filesystem so you can put whatever
-+         * path you want here.
-+         */
-+        if(strstr(file_mask,".shm")) {
-+            mktemp(file_mask);
-+            fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
-+            if(fd == -1) {
-+                apc_eprint("apc_mmap: shm_open on %s failed:", file_mask);
-+                return (void *)-1;
-+            }
-+            if (ftruncate(fd, size) < 0) {
-+                close(fd);
-+                shm_unlink(file_mask);
-+                apc_eprint("apc_mmap: ftruncate failed:");
-+                return (void *)-1;
-+            }
-+            shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-+            shm_unlink(file_mask);
-+            close(fd);
-+        }
-+        /*
-+         * Support anonymous mmap through the /dev/zero interface as well
-+         */
-+        else if(!strcmp(file_mask,"/dev/zero")) {
-+            fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
-+            if(fd == -1) {
-+                apc_eprint("apc_mmap: open on /dev/zero failed:");
-+                return (void *)-1;
-+            }
-+            shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
-+            close(fd);
-+        }
-+        /* 
-+         * Otherwise we do a normal filesystem mmap
-+         */
-+        else {
-+            fd = mkstemp(file_mask);
-+            if(fd == -1) {
-+                apc_eprint("apc_mmap: mkstemp on %s failed:", file_mask);
-+                return (void *)-1;
-+            }
-+            if (ftruncate(fd, size) < 0) {
-+                close(fd);
-+                unlink(file_mask);
-+                apc_eprint("apc_mmap: ftruncate failed:");
-+            }
-+            shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NOSYNC, fd, 0);
-+            close(fd);
-+            unlink(file_mask);
-+        }
-+    }
-+    if((int)shmaddr == -1) {
-+        apc_eprint("apc_mmap: mmap failed:");
-+    }
-+    return shmaddr;
-+}
-+
-+void apc_unmap(void* shmaddr, size_t size)
-+{
-+    if (munmap(shmaddr, size) < 0) {
-+        apc_wprint("apc_unmap: munmap failed:");
-+    }
-+}
++/* {{{ generic locking macros */
++#define CREATE_LOCK(lock)     apc_lck_create(NULL, 0, 1, lock)
++#define DESTROY_LOCK(lock)    apc_lck_destroy(lock)
++#define LOCK(lock)          { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(lock); }
++#define RDLOCK(lock)        { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(lock); }
++#define UNLOCK(lock)        { apc_lck_unlock(lock); HANDLE_UNBLOCK_INTERRUPTIONS(); }
++/* }}} */
 +
++#if defined(APC_SEM_LOCKS)
++#define APC_LOCK_TYPE "IPC Semaphore"
++#define RDLOCK_AVAILABLE 0
++#define NONBLOCKING_LOCK_AVAILABLE 1 
++#define apc_lck_t int
++#define apc_lck_create(a,b,c,d) d=apc_sem_create(NULL,(b),(c))
++#define apc_lck_destroy(a)    apc_sem_destroy(a)
++#define apc_lck_lock(a)       apc_sem_lock(a)
++#define apc_lck_nb_lock(a)    apc_sem_nonblocking_lock(a)
++#define apc_lck_rdlock(a)     apc_sem_lock(a)
++#define apc_lck_unlock(a)     apc_sem_unlock(a)
++#elif defined(APC_PTHREADMUTEX_LOCKS)
++#define APC_LOCK_TYPE "pthread mutex Locks"
++#define RDLOCK_AVAILABLE 0
++#define NONBLOCKING_LOCK_AVAILABLE 1
++#define apc_lck_t pthread_mutex_t 
++#define apc_lck_create(a,b,c,d) apc_pthreadmutex_create((pthread_mutex_t*)&d)
++#define apc_lck_destroy(a)    apc_pthreadmutex_destroy(&a)
++#define apc_lck_lock(a)       apc_pthreadmutex_lock(&a)
++#define apc_lck_nb_lock(a)    apc_pthreadmutex_nonblocking_lock(&a)
++#define apc_lck_rdlock(a)     apc_pthreadmutex_lock(&a)
++#define apc_lck_unlock(a)     apc_pthreadmutex_unlock(&a)
++#elif defined(APC_SPIN_LOCKS)
++#define APC_LOCK_TYPE "spin Locks"
++#define RDLOCK_AVAILABLE 0
++#define NONBLOCKING_LOCK_AVAILABLE APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE
++#define apc_lck_t slock_t 
++#define apc_lck_create(a,b,c,d) apc_slock_create((slock_t*)&(d))
++#define apc_lck_destroy(a)    apc_slock_destroy(&a)
++#define apc_lck_lock(a)       apc_slock_lock(&a)
++#define apc_lck_nb_lock(a)    apc_slock_nonblocking_lock(&a)
++#define apc_lck_rdlock(a)     apc_slock_lock(&a)
++#define apc_lck_unlock(a)     apc_slock_unlock(&a)
++#else
++#define APC_LOCK_TYPE "File Locks"
++#define RDLOCK_AVAILABLE 1
++#ifdef PHP_WIN32
++#define NONBLOCKING_LOCK_AVAILABLE 0
++#else
++#define NONBLOCKING_LOCK_AVAILABLE 1
++#endif
++#define apc_lck_t int
++#define apc_lck_create(a,b,c,d) d=apc_fcntl_create((a))
++#define apc_lck_destroy(a)    apc_fcntl_destroy(a)
++#define apc_lck_lock(a)       apc_fcntl_lock(a)
++#define apc_lck_nb_lock(a)    apc_fcntl_nonblocking_lock(a)
++#define apc_lck_rdlock(a)     apc_fcntl_rdlock(a)
++#define apc_lck_unlock(a)     apc_fcntl_unlock(a)
 +#endif
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc.php php-5.2.5/ext/apc/apc.php
---- php-5.2.5-orig/ext/apc/apc.php     1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc.php  2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,1326 @@
-+<?php
++#endif
+diff -Naur php-5.3.1.orig/ext/apc/apc_main.c php-5.3.1/ext/apc/apc_main.c
+--- php-5.3.1.orig/ext/apc/apc_main.c  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_main.c       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,957 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -6943,1401 +6885,958 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc.php php-5.2.5/ext/apc/apc.php
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Ralf Becker <beckerr@php.net>                               |
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
 +  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  |          Ilia Alshanetsky <ilia@prohost.org>                         |
++  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
++  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
 +  +----------------------------------------------------------------------+
 +
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
++
 +   All other licensing and usage conditions are those of the PHP Group.
 +
 + */
 +
-+$VERSION='$Id: apc.php,v 3.68 2007/07/22 00:25:48 gopalv Exp $';
++/* $Id: apc_main.c 284282 2009-07-17 21:50:33Z shire $ */
 +
-+////////// READ OPTIONAL CONFIGURATION FILE ////////////
-+if (file_exists("apc.conf.php")) include("apc.conf.php");
-+////////////////////////////////////////////////////////
++#include "apc_php.h"
++#include "apc_main.h"
++#include "apc.h"
++#include "apc_lock.h"
++#include "apc_cache.h"
++#include "apc_compile.h"
++#include "apc_globals.h"
++#include "apc_sma.h"
++#include "apc_stack.h"
++#include "apc_zend.h"
++#include "apc_pool.h"
++#include "SAPI.h"
++#include "php_scandir.h"
++#include "ext/standard/php_var.h"
++#include "ext/standard/md5.h"
 +
-+////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
++/* {{{ module variables */
 +
-+defaults('USE_AUTHENTICATION',1);                     // Use (internal) authentication - best choice if 
-+                                                                                      // no other authentication is available
-+                                                                                      // If set to 0:
-+                                                                                      //  There will be no further authentication. You 
-+                                                                                      //  will have to handle this by yourself!
-+                                                                                      // If set to 1:
-+                                                                                      //  You need to change ADMIN_PASSWORD to make
-+                                                                                      //  this work!
-+defaults('ADMIN_USERNAME','apc');                     // Admin Username
-+defaults('ADMIN_PASSWORD','password');        // Admin Password - CHANGE THIS TO ENABLE!!!
++/* pointer to the original Zend engine compile_file function */
++typedef zend_op_array* (zend_compile_t)(zend_file_handle*, int TSRMLS_DC);
++static zend_compile_t *old_compile_file;
 +
-+// (beckerr) I'm using a clear text password here, because I've no good idea how to let 
-+//           users generate a md5 or crypt password in a easy way to fill it in above
++/* }}} */
 +
-+//defaults('DATE_FORMAT', "d.m.Y H:i:s");     // German
-+defaults('DATE_FORMAT', 'Y/m/d H:i:s');       // US
++/* {{{ get/set old_compile_file (to interact with other extensions that need the compile hook) */
++static zend_compile_t* set_compile_hook(zend_compile_t *ptr)
++{
++    zend_compile_t *retval = old_compile_file;
 +
-+defaults('GRAPH_SIZE',200);                                   // Image size
++    if (ptr != NULL) old_compile_file = ptr;
++    return retval;
++}
++/* }}} */
 +
-+////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
++/* {{{ install_function */
++static int install_function(apc_function_t fn, apc_context_t* ctxt, int lazy TSRMLS_DC)
++{
++    int status;
 +
 +
-+// "define if not defined"
-+function defaults($d,$v) {
-+      if (!defined($d)) define($d,$v); // or just @define(...)
++    if(lazy && fn.name[0] != '\0' && strncmp(fn.name, "__autoload", fn.name_len) != 0) {
++        status = zend_hash_add(APCG(lazy_function_table),
++                              fn.name,
++                              fn.name_len+1,
++                              &fn,
++                              sizeof(apc_function_t),
++                              NULL);
++    } else {
++        zend_function *func = apc_copy_function_for_execution(fn.function, ctxt);
++        status = zend_hash_add(EG(function_table),
++                              fn.name,
++                              fn.name_len+1,
++                              func,
++                              sizeof(fn.function[0]),
++                              NULL);
++        efree(func);
++    }
++
++    if (status == FAILURE) {
++        /* apc_eprint("Cannot redeclare %s()", fn.name); */
++    }
++
++    return status;
 +}
++/* }}} */
 +
-+// rewrite $PHP_SELF to block XSS attacks
-+//
-+$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES) : '';
-+$time = time();
-+$host = getenv('HOSTNAME');
-+if($host) { $host = '('.$host.')'; }
++/* {{{ apc_lookup_function_hook */
++int apc_lookup_function_hook(char *name, int len, ulong hash, zend_function **fe) {
++    apc_function_t *fn;
++    int status = FAILURE;
++    apc_context_t ctxt = {0,};
++    TSRMLS_FETCH();
 +
-+// operation constants
-+define('OB_HOST_STATS',1);
-+define('OB_SYS_CACHE',2);
-+define('OB_USER_CACHE',3);
-+define('OB_SYS_CACHE_DIR',4);
-+define('OB_VERSION_CHECK',9);
++    ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, apc_sma_protect, apc_sma_unprotect);
++    ctxt.copy = APC_COPY_OUT_OPCODE;
 +
-+// check validity of input variables
-+$vardom=array(
-+      'OB'    => '/^\d+$/',                   // operational mode switch
-+      'CC'    => '/^[01]$/',                  // clear cache requested
-+      'DU'    => '/^.*$/',                    // Delete User Key
-+      'SH'    => '/^[a-z0-9]+$/',             // shared object description
++    if(zend_hash_quick_find(APCG(lazy_function_table), name, len, hash, (void**)&fn) == SUCCESS) {
++        *fe = apc_copy_function_for_execution(fn->function, &ctxt);
++        status = zend_hash_add(EG(function_table),
++                                  fn->name,
++                                  fn->name_len+1,
++                                  *fe,
++                                  sizeof(zend_function),
++                                  NULL);
++    }
 +
-+      'IMG'   => '/^[123]$/',                 // image to generate
-+      'LO'    => '/^1$/',                             // login requested
++    return status;
++}
++/* }}} */
 +
-+      'COUNT' => '/^\d+$/',                   // number of line displayed in list
-+      'SCOPE' => '/^[AD]$/',                  // list view scope
-+      'SORT1' => '/^[AHSMCDTZ]$/',    // first sort key
-+      'SORT2' => '/^[DA]$/',                  // second sort key
-+      'AGGR'  => '/^\d+$/',                   // aggregation by dir level
-+      'SEARCH'        => '~^[a-zA-Z0-1/_.-]*$~'                       // aggregation by dir level
-+);
++/* {{{ install_class */
++static int install_class(apc_class_t cl, apc_context_t* ctxt, int lazy TSRMLS_DC)
++{
++    zend_class_entry* class_entry = cl.class_entry;
++    zend_class_entry* parent = NULL;
++    int status;
++    zend_class_entry** allocated_ce = NULL;
 +
-+// default cache mode
-+$cache_mode='opcode';
++    /* Special case for mangled names. Mangled names are unique to a file.
++     * There is no way two classes with the same mangled name will occur,
++     * unless a file is included twice. And if in case, a file is included
++     * twice, all mangled name conflicts can be ignored and the class redeclaration
++     * error may be deferred till runtime of the corresponding DECLARE_CLASS
++     * calls.
++     */
 +
-+// cache scope
-+$scope_list=array(
-+      'A' => 'cache_list',
-+      'D' => 'deleted_list'
-+);
++    if(cl.name_len != 0 && cl.name[0] == '\0') {
++        if(zend_hash_exists(CG(class_table), cl.name, cl.name_len+1)) {
++            return SUCCESS;
++        }
++    }
 +
-+// handle POST and GET requests
-+if (empty($_REQUEST)) {
-+      if (!empty($_GET) && !empty($_POST)) {
-+              $_REQUEST = array_merge($_GET, $_POST);
-+      } else if (!empty($_GET)) {
-+              $_REQUEST = $_GET;
-+      } else if (!empty($_POST)) {
-+              $_REQUEST = $_POST;
-+      } else {
-+              $_REQUEST = array();
-+      }
-+}
++    if(lazy && cl.name_len != 0 && cl.name[0] != '\0') {
++        status = zend_hash_add(APCG(lazy_class_table),
++                               cl.name,
++                               cl.name_len+1,
++                               &cl,
++                               sizeof(apc_class_t),
++                               NULL);
++        if(status == FAILURE) {
++            zend_error(E_ERROR, "Cannot redeclare class %s", cl.name);
++        }
++        return status;
++    }
 +
-+// check parameter syntax
-+foreach($vardom as $var => $dom) {
-+      if (!isset($_REQUEST[$var])) {
-+              $MYREQUEST[$var]=NULL;
-+      } else if (!is_array($_REQUEST[$var]) && preg_match($dom.'D',$_REQUEST[$var])) {
-+              $MYREQUEST[$var]=$_REQUEST[$var];
-+      } else {
-+              $MYREQUEST[$var]=$_REQUEST[$var]=NULL;
-+      }
-+}
++    /*
++     * XXX: We need to free this somewhere...
++     */
++    allocated_ce = apc_php_malloc(sizeof(zend_class_entry*));
 +
-+// check parameter sematics
-+if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A";
-+if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H";
-+if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D";
-+if (empty($MYREQUEST['OB']))  $MYREQUEST['OB']=OB_HOST_STATS;
-+if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20;
-+if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A';
++    if(!allocated_ce) {
++        return FAILURE;
++    }
 +
-+$MY_SELF=
-+      "$PHP_SELF".
-+      "?SCOPE=".$MYREQUEST['SCOPE'].
-+      "&SORT1=".$MYREQUEST['SORT1'].
-+      "&SORT2=".$MYREQUEST['SORT2'].
-+      "&COUNT=".$MYREQUEST['COUNT'];
-+$MY_SELF_WO_SORT=
-+      "$PHP_SELF".
-+      "?SCOPE=".$MYREQUEST['SCOPE'].
-+      "&COUNT=".$MYREQUEST['COUNT'];
++    *allocated_ce =
++    class_entry =
++        apc_copy_class_entry_for_execution(cl.class_entry, ctxt);
 +
-+// authentication needed?
-+//
-+if (!USE_AUTHENTICATION) {
-+      $AUTHENTICATED=1;
-+} else {
-+      $AUTHENTICATED=0;
-+      if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
 +
-+              if (!isset($_SERVER['PHP_AUTH_USER']) ||
-+                      !isset($_SERVER['PHP_AUTH_PW']) ||
-+                      $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||
-+                      $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
-+                      Header("WWW-Authenticate: Basic realm=\"APC Login\"");
-+                      Header("HTTP/1.0 401 Unauthorized");
++    /* restore parent class pointer for compile-time inheritance */
++    if (cl.parent_name != NULL) {
++        zend_class_entry** parent_ptr = NULL;
++        /*
++         * __autoload brings in the old issues with mixed inheritance.
++         * When a statically inherited class triggers autoload, it runs
++         * afoul of a potential require_once "parent.php" in the previous 
++         * line, which when executed provides the parent class, but right
++         * now goes and hits __autoload which could fail. 
++         * 
++         * missing parent == re-compile. 
++         *
++         * whether __autoload is enabled or not, because __autoload errors
++         * cause php to die.
++         *
++         * Aside: Do NOT pass *strlen(cl.parent_name)+1* because
++         * zend_lookup_class_ex does it internally anyway!
++         */
++        status = zend_lookup_class_ex(cl.parent_name,
++                                    strlen(cl.parent_name), 
++                                    0,
++                                    &parent_ptr TSRMLS_CC);
++        if (status == FAILURE) {
++            if(APCG(report_autofilter)) {
++                apc_wprint("Dynamic inheritance detected for class %s", cl.name);
++            }
++            class_entry->parent = NULL;
++            return status;
++        }
++        else {
++            parent = *parent_ptr;
++            class_entry->parent = parent;
++            zend_do_inheritance(class_entry, parent TSRMLS_CC);
++        }
 +
-+                      echo <<<EOB
-+                              <html><body>
-+                              <h1>Rejected!</h1>
-+                              <big>Wrong Username or Password!</big><br/>&nbsp;<br/>&nbsp;
-+                              <big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
-+                              </body></html>
-+EOB;
-+                      exit;
-+                      
-+              } else {
-+                      $AUTHENTICATED=1;
-+              }
-+      }
++
++    }
++
++    status = zend_hash_add(EG(class_table),
++                           cl.name,
++                           cl.name_len+1,
++                           allocated_ce,
++                           sizeof(zend_class_entry*),
++                           NULL);
++
++    if (status == FAILURE) {
++        apc_eprint("Cannot redeclare class %s", cl.name);
++    }
++    return status;
 +}
-+      
-+// select cache mode
-+if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {
-+      $cache_mode='user';
++/* }}} */
++
++/* {{{ apc_lookup_class_hook */
++int apc_lookup_class_hook(char *name, int len, ulong hash, zend_class_entry ***ce) {
++
++    apc_class_t *cl;
++    apc_context_t ctxt = {0,};
++    TSRMLS_FETCH();
++
++    if(zend_is_compiling(TSRMLS_C)) { return FAILURE; }
++
++    if(zend_hash_quick_find(APCG(lazy_class_table), name, len, hash, (void**)&cl) == FAILURE) {
++        return FAILURE;
++    }
++
++    ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, apc_sma_protect, apc_sma_unprotect);
++    ctxt.copy = APC_COPY_OUT_OPCODE;
++
++    if(install_class(*cl, &ctxt, 0 TSRMLS_CC) == FAILURE) {
++        apc_wprint("apc_lookup_class_hook: could not install %s", name);
++        return FAILURE;
++    }
++
++    if(zend_hash_quick_find(EG(class_table), name, len, hash, (void**)ce) == FAILURE) {
++        apc_wprint("apc_lookup_class_hook: known error trying to fetch class %s", name);
++        return FAILURE;
++    }
++
++    return SUCCESS;
++
 +}
-+// clear cache
-+if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
-+      apc_clear_cache($cache_mode);
++/* }}} */
++
++/* {{{ uninstall_class */
++static int uninstall_class(apc_class_t cl TSRMLS_DC)
++{
++    int status;
++
++    status = zend_hash_del(EG(class_table),
++                           cl.name,
++                           cl.name_len+1);
++    if (status == FAILURE) {
++        apc_eprint("Cannot delete class %s", cl.name);
++    }
++    return status;
 +}
++/* }}} */
 +
-+if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) {
-+      apc_delete($MYREQUEST['DU']);
++/* {{{ copy_function_name (taken from zend_builtin_functions.c to ensure future compatibility with APC) */
++static int copy_function_name(apc_function_t *pf TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
++{
++    zval *internal_ar = va_arg(args, zval *),
++         *user_ar     = va_arg(args, zval *);
++    zend_function *func = pf->function;
++
++    if (hash_key->nKeyLength == 0 || hash_key->arKey[0] == 0) {
++        return 0;
++    }
++
++    if (func->type == ZEND_INTERNAL_FUNCTION) {
++        add_next_index_stringl(internal_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
++    } else if (func->type == ZEND_USER_FUNCTION) {
++        add_next_index_stringl(user_ar, hash_key->arKey, hash_key->nKeyLength-1, 1);
++    }
++
++    return 0;
 +}
 +
-+if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) {
-+      echo "No cache info available.  APC does not appear to be running.";
-+  exit;
++/* {{{ copy_class_or_interface_name (taken from zend_builtin_functions.c to ensure future compatibility with APC) */
++static int copy_class_or_interface_name(apc_class_t *cl TSRMLS_DC, int num_args, va_list args, zend_hash_key *hash_key)
++{
++    zval *array = va_arg(args, zval *);
++    zend_uint mask = va_arg(args, zend_uint);
++    zend_uint comply = va_arg(args, zend_uint);
++    zend_uint comply_mask = (comply)? mask:0;
++    zend_class_entry *ce  = cl->class_entry;
++
++    if ((hash_key->nKeyLength==0 || hash_key->arKey[0]!=0)
++        && (comply_mask == (ce->ce_flags & mask))) {
++        add_next_index_stringl(array, ce->name, ce->name_length, 1);
++    }
++    return ZEND_HASH_APPLY_KEEP;
 +}
++/* }}} */
 +
-+$cache_user = apc_cache_info('user', 1);  
-+$mem=apc_sma_info();
-+if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; }  // Avoid division by 0 errors on a cache clear
++/* }}} */
 +
-+// don't cache this page
-+//
-+header("Cache-Control: no-store, no-cache, must-revalidate");  // HTTP/1.1
-+header("Cache-Control: post-check=0, pre-check=0", false);
-+header("Pragma: no-cache");                                    // HTTP/1.0
++/* {{{ apc_defined_function_hook */
++int apc_defined_function_hook(zval *internal, zval *user) {
++    TSRMLS_FETCH();
++  zend_hash_apply_with_arguments(APCG(lazy_function_table) TSRMLS_CC, (apply_func_args_t) copy_function_name, 2, internal, user);
++  return 1;
++}
++/* }}} */
 +
-+function duration($ts) {
-+    global $time;
-+    $years = (int)((($time - $ts)/(7*86400))/52.177457);
-+    $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));
-+    $weeks = (int)(($rem)/(7*86400));
-+    $days = (int)(($rem)/86400) - $weeks*7;
-+    $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;
-+    $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;
-+    $str = '';
-+    if($years==1) $str .= "$years year, ";
-+    if($years>1) $str .= "$years years, ";
-+    if($weeks==1) $str .= "$weeks week, ";
-+    if($weeks>1) $str .= "$weeks weeks, ";
-+    if($days==1) $str .= "$days day,";
-+    if($days>1) $str .= "$days days,";
-+    if($hours == 1) $str .= " $hours hour and";
-+    if($hours>1) $str .= " $hours hours and";
-+    if($mins == 1) $str .= " 1 minute";
-+    else $str .= " $mins minutes";
-+    return $str;
++/* {{{ apc_declared_class_hook */
++int apc_declared_class_hook(zval *classes, zend_uint mask, zend_uint comply) {
++    TSRMLS_FETCH();
++  zend_hash_apply_with_arguments(APCG(lazy_class_table) TSRMLS_CC, (apply_func_args_t) copy_class_or_interface_name, 3, classes, mask, comply);
++  return 1;
 +}
++/* }}} */
 +
-+// create graphics
-+//
-+function graphics_avail() {
-+      return extension_loaded('gd');
++/* {{{ compare_file_handles */
++static int compare_file_handles(void* a, void* b)
++{
++    zend_file_handle* fh1 = (zend_file_handle*)a;
++    zend_file_handle* fh2 = (zend_file_handle*)b;
++    return (fh1->type == fh2->type && 
++            fh1->filename == fh2->filename &&
++            fh1->opened_path == fh2->opened_path);
 +}
-+if (isset($MYREQUEST['IMG']))
++/* }}} */
++
++/* {{{ cached_compile */
++static zend_op_array* cached_compile(zend_file_handle* h,
++                                        int type,
++                                        apc_context_t* ctxt TSRMLS_DC)
 +{
-+      if (!graphics_avail()) {
-+              exit(0);
-+      }
++    apc_cache_entry_t* cache_entry;
++    int i, ii;
 +
-+      function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
-+              $r=$diameter/2;
-+              $w=deg2rad((360+$start+($end-$start)/2)%360);
++    cache_entry = (apc_cache_entry_t*) apc_stack_top(APCG(cache_stack));
++    assert(cache_entry != NULL);
 +
-+              
-+              if (function_exists("imagefilledarc")) {
-+                      // exists only if GD 2.0.1 is avaliable
-+                      imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
-+                      imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
-+                      imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
-+              } else {
-+                      imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
-+                      imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
-+                      imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
-+                      imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
-+                      imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
-+                      imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
-+              }
-+              if ($text) {
-+                      if ($placeindex>0) {
-+                              imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
-+                              imagestring($im,4,$diameter, $placeindex*12,$text,$color1);     
-+                              
-+                      } else {
-+                              imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
-+                      }
-+              }
-+      } 
++    if (cache_entry->data.file.classes) {
++        for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
++            if(install_class(cache_entry->data.file.classes[i], ctxt, APCG(lazy_classes) TSRMLS_CC) == FAILURE) {
++                goto default_compile;
++            }
++        }
++    }
 +
-+      function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
-+              $r=$diameter/2;
-+              $w=deg2rad((360+$start+($end-$start)/2)%360);
++    if (cache_entry->data.file.functions) {
++        for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
++            install_function(cache_entry->data.file.functions[i], ctxt, APCG(lazy_functions) TSRMLS_CC);
++        }
++    }
 +
-+              if ($placeindex>0) {
-+                      imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
-+                      imagestring($im,4,$diameter, $placeindex*12,$text,$color1);     
-+                              
-+              } else {
-+                      imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
-+              }
-+      } 
-+      
-+      function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
-+              global $col_black;
-+              $x1=$x+$w-1;
-+              $y1=$y+$h-1;
++    apc_do_halt_compiler_register(cache_entry->data.file.filename, cache_entry->data.file.halt_offset TSRMLS_CC);
 +
-+              imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
-+              if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
-+              else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
-+              imagerectangle($im, $x, $y1, $x1, $y, $color1);
-+              if ($text) {
-+                      if ($placeindex>0) {
-+                      
-+                              if ($placeindex<16)
-+                              {
-+                                      $px=5;
-+                                      $py=$placeindex*12+6;
-+                                      imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
-+                                      imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
-+                                      imagestring($im,2,$px,$py-6,$text,$color1);     
-+                                      
-+                              } else {
-+                                      if ($placeindex<31) {
-+                                              $px=$x+40*2;
-+                                              $py=($placeindex-15)*12+6;
-+                                      } else {
-+                                              $px=$x+40*2+100*intval(($placeindex-15)/15);
-+                                              $py=($placeindex%15)*12+6;
-+                                      }
-+                                      imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
-+                                      imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
-+                                      imagestring($im,2,$px+2,$py-6,$text,$color1);   
-+                              }
-+                      } else {
-+                              imagestring($im,4,$x+5,$y1-16,$text,$color1);
-+                      }
-+              }
-+      }
 +
++    return apc_copy_op_array_for_execution(NULL, cache_entry->data.file.op_array, ctxt TSRMLS_CC);
 +
-+      $size = GRAPH_SIZE; // image size
-+      if ($MYREQUEST['IMG']==3)
-+              $image = imagecreate(2*$size+150, $size+10);
-+      else
-+              $image = imagecreate($size+50, $size+10);
++default_compile:
 +
-+      $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
-+      $col_red   = imagecolorallocate($image, 0xD0, 0x60,  0x30);
-+      $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
-+      $col_black = imagecolorallocate($image,   0,   0,   0);
-+      imagecolortransparent($image,$col_white);
++    if(APCG(report_autofilter)) {
++        apc_wprint("Autofiltering %s", h->opened_path);
++    }
 +
-+      switch ($MYREQUEST['IMG']) {
-+      
-+      case 1:
-+              $s=$mem['num_seg']*$mem['seg_size'];
-+              $a=$mem['avail_mem'];
-+              $x=$y=$size/2;
-+              $fuzz = 0.000001;
++    if(cache_entry->data.file.classes) {
++        for(ii = 0; ii < i ; ii++) {
++            uninstall_class(cache_entry->data.file.classes[ii] TSRMLS_CC);
++        }
++    }
 +
-+              // This block of code creates the pie chart.  It is a lot more complex than you
-+              // would expect because we try to visualize any memory fragmentation as well.
-+              $angle_from = 0;
-+              $string_placement=array();
-+              for($i=0; $i<$mem['num_seg']; $i++) {   
-+                      $ptr = 0;
-+                      $free = $mem['block_lists'][$i];
-+                      foreach($free as $block) {
-+                              if($block['offset']!=$ptr) {       // Used block
-+                                      $angle_to = $angle_from+($block['offset']-$ptr)/$s;
-+                                      if(($angle_to+$fuzz)>1) $angle_to = 1;
-+                                      fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
-+                                      if (($angle_to-$angle_from)>0.05) {
-+                                              array_push($string_placement, array($angle_from,$angle_to));
-+                                      }
-+                                      $angle_from = $angle_to;
-+                              }
-+                              $angle_to = $angle_from+($block['size'])/$s;
-+                              if(($angle_to+$fuzz)>1) $angle_to = 1;
-+                              fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);
-+                              if (($angle_to-$angle_from)>0.05) {
-+                                      array_push($string_placement, array($angle_from,$angle_to));
-+                              }
-+                              $angle_from = $angle_to;
-+                              $ptr = $block['offset']+$block['size'];
-+                      }
-+                      if ($ptr < $mem['seg_size']) { // memory at the end 
-+                              $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;
-+                              if(($angle_to+$fuzz)>1) $angle_to = 1;
-+                              fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
-+                              if (($angle_to-$angle_from)>0.05) {
-+                                      array_push($string_placement, array($angle_from,$angle_to));
-+                              }
-+                      }
-+              }
-+              foreach ($string_placement as $angle) {
-+                      text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0])));
-+              }
-+              break;
-+              
-+      case 2: 
-+              $s=$cache['num_hits']+$cache['num_misses'];
-+              $a=$cache['num_hits'];
-+              
-+              fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
-+              fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
-+              break;
-+              
-+      case 3:
-+              $s=$mem['num_seg']*$mem['seg_size'];
-+              $a=$mem['avail_mem'];
-+              $x=130;
-+              $y=1;
-+              $j=1;
++    apc_stack_pop(APCG(cache_stack)); /* pop out cache_entry */
 +
-+              // This block of code creates the bar chart.  It is a lot more complex than you
-+              // would expect because we try to visualize any memory fragmentation as well.
-+              for($i=0; $i<$mem['num_seg']; $i++) {   
-+                      $ptr = 0;
-+                      $free = $mem['block_lists'][$i];
-+                      foreach($free as $block) {
-+                              if($block['offset']!=$ptr) {       // Used block
-+                                      $h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;
-+                                      if ($h>0) {
-+                                                $j++;
-+                                              if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j);
-+                                                else fill_box($image,$x,$y,50,$h,$col_black,$col_red);
-+                                        }
-+                                      $y+=$h;
-+                              }
-+                              $h=(GRAPH_SIZE-5)*($block['size'])/$s;
-+                              if ($h>0) {
-+                                        $j++;
-+                                      if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j);
-+                                      else fill_box($image,$x,$y,50,$h,$col_black,$col_green);
-+                                }
-+                              $y+=$h;
-+                              $ptr = $block['offset']+$block['size'];
-+                      }
-+                      if ($ptr < $mem['seg_size']) { // memory at the end 
-+                              $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
-+                              if ($h > 0) {
-+                                      fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);
-+                              }
-+                      }
-+              }
-+              break;
-+      case 4: 
-+              $s=$cache['num_hits']+$cache['num_misses'];
-+              $a=$cache['num_hits'];
-+                      
-+              fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
-+              fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
-+              break;
-+      
-+      }
-+      header("Content-type: image/png");
-+      imagepng($image);
-+      exit;
-+}
++    apc_cache_release(apc_cache, cache_entry);
 +
-+// pretty printer for byte values
-+//
-+function bsize($s) {
-+      foreach (array('','K','M','G') as $i => $k) {
-+              if ($s < 1024) break;
-+              $s/=1024;
-+      }
-+      return sprintf("%5.1f %sBytes",$s,$k);
-+}
++    /* cannot free up cache data yet, it maybe in use */
 +
-+// sortable table header in "scripts for this host" view
-+function sortheader($key,$name,$extra='') {
-+      global $MYREQUEST, $MY_SELF_WO_SORT;
-+      
-+      if ($MYREQUEST['SORT1']==$key) {
-+              $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';
-+      }
-+      return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>";
++    zend_llist_del_element(&CG(open_files), h, compare_file_handles); /* We leak fds without this hack */
 +
-+}
++    /* WARNING: zend_llist shallow copies - so element delete via the 
++     * zend_file_handle_dtor leaves h->opened_path dangling onto bad memory.
++     */
 +
-+// create menu entry 
-+function menu_entry($ob,$title) {
-+      global $MYREQUEST,$MY_SELF;
-+      if ($MYREQUEST['OB']!=$ob) {
-+              return "<li><a href=\"$MY_SELF&OB=$ob\">$title</a></li>";
-+      } else if (empty($MYREQUEST['SH'])) {
-+              return "<li><span class=active>$title</span></li>";
-+      } else {
-+              return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>";        
-+      }
-+}
++    h->opened_path = NULL;
++    h->type = ZEND_HANDLE_FILENAME;
++    if(h->free_filename) h->filename = NULL;
 +
-+function put_login_link($s="Login")
-+{
-+      global $MY_SELF,$MYREQUEST,$AUTHENTICATED;
-+      // needs ADMIN_PASSWORD to be changed!
-+      //
-+      if (!USE_AUTHENTICATION) {
-+              return;
-+      } else if (ADMIN_PASSWORD=='password')
-+      {
-+              print <<<EOB
-+                      <a href="#" onClick="javascript:alert('You need to set a password at the top of apc.php before this will work!');return false";>$s</a>
-+EOB;
-+      } else if ($AUTHENTICATED) {
-+              print <<<EOB
-+                      '{$_SERVER['PHP_AUTH_USER']}'&nbsp;logged&nbsp;in!
-+EOB;
-+      } else{
-+              print <<<EOB
-+                      <a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a>
-+EOB;
-+      }
++    return NULL;
 +}
++/* }}} */
 +
++/* {{{ apc_compile_cache_entry  */
++zend_bool apc_compile_cache_entry(apc_cache_key_t key, zend_file_handle* h, int type, time_t t, zend_op_array** op_array, apc_cache_entry_t** cache_entry TSRMLS_DC) {
++    int num_functions, num_classes;
++    apc_function_t* alloc_functions;
++    zend_op_array* alloc_op_array;
++    apc_class_t* alloc_classes;
++    char *path;
++    apc_context_t ctxt;
 +
-+?>
-+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-+<html>
-+<head><title>APC INFO <?php echo $host ?></title>
-+<style><!--
-+body { background:white; font-size:100.01%; margin:0; padding:0; }
-+body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
-+* html body   {font-size:0.8em}
-+* html p      {font-size:0.8em}
-+* html td     {font-size:0.8em}
-+* html th     {font-size:0.8em}
-+* html input  {font-size:0.8em}
-+* html submit {font-size:0.8em}
-+td { vertical-align:top }
-+a { color:black; font-weight:none; text-decoration:none; }
-+a:hover { text-decoration:underline; }
-+div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
++    /* remember how many functions and classes existed before compilation */
++    num_functions = zend_hash_num_elements(CG(function_table));
++    num_classes   = zend_hash_num_elements(CG(class_table));
 +
++    /* compile the file using the default compile function,  *
++     * we set *op_array here so we return opcodes during     *
++     * a failure.  We should not return prior to this line.  */
++    *op_array = old_compile_file(h, type TSRMLS_CC);
++    if (*op_array == NULL) {
++        return FAILURE;
++    }
 +
-+div.head div.login {
-+      position:absolute;
-+      right: 1em;
-+      top: 1.2em;
-+      color:white;
-+      width:6em;
-+      }
-+div.head div.login a {
-+      position:absolute;
-+      right: 0em;
-+      background:rgb(119,123,180);
-+      border:solid rgb(102,102,153) 2px;
-+      color:white;
-+      font-weight:bold;
-+      padding:0.1em 0.5em 0.1em 0.5em;
-+      text-decoration:none;
-+      }
-+div.head div.login a:hover {
-+      background:rgb(193,193,244);
-+      }
++    ctxt.pool = apc_pool_create(APC_MEDIUM_POOL, apc_sma_malloc, apc_sma_free, 
++                                                 apc_sma_protect, apc_sma_unprotect);
++    if (!ctxt.pool) {
++        apc_wprint("Unable to allocate memory for pool.");
++        return FAILURE;
++    }
++    ctxt.copy = APC_COPY_IN_OPCODE;
 +
-+h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
-+* html h1.apc { margin-bottom:-7px; }
-+h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
-+h1.apc div.logo span.logo {
-+      background:rgb(119,123,180);
-+      color:black;
-+      border-right: solid black 1px;
-+      border-bottom: solid black 1px;
-+      font-style:italic;
-+      font-size:1em;
-+      padding-left:1.2em;
-+      padding-right:1.2em;
-+      text-align:right;
-+      }
-+h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
-+h1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
-+h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
-+hr.apc {
-+      background:white;
-+      border-bottom:solid rgb(102,102,153) 1px;
-+      border-style:none;
-+      border-top:solid rgb(102,102,153) 10px;
-+      height:12px;
-+      margin:0;
-+      margin-top:1px;
-+      padding:0;
-+}
++    if(APCG(file_md5)) {
++        int n;
++        unsigned char buf[1024];
++        PHP_MD5_CTX context;
++        php_stream *stream;
++        char *filename;
 +
-+ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
-+ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
-+ol.menu a {
-+      background:rgb(153,153,204);
-+      border:solid rgb(102,102,153) 2px;
-+      color:white;
-+      font-weight:bold;
-+      margin-right:0em;
-+      padding:0.1em 0.5em 0.1em 0.5em;
-+      text-decoration:none;
-+      margin-left: 5px;
-+      }
-+ol.menu a.child_active {
-+      background:rgb(153,153,204);
-+      border:solid rgb(102,102,153) 2px;
-+      color:white;
-+      font-weight:bold;
-+      margin-right:0em;
-+      padding:0.1em 0.5em 0.1em 0.5em;
-+      text-decoration:none;
-+      border-left: solid black 5px;
-+      margin-left: 0px;
-+      }
-+ol.menu span.active {
-+      background:rgb(153,153,204);
-+      border:solid rgb(102,102,153) 2px;
-+      color:black;
-+      font-weight:bold;
-+      margin-right:0em;
-+      padding:0.1em 0.5em 0.1em 0.5em;
-+      text-decoration:none;
-+      border-left: solid black 5px;
-+      }
-+ol.menu span.inactive {
-+      background:rgb(193,193,244);
-+      border:solid rgb(182,182,233) 2px;
-+      color:white;
-+      font-weight:bold;
-+      margin-right:0em;
-+      padding:0.1em 0.5em 0.1em 0.5em;
-+      text-decoration:none;
-+      margin-left: 5px;
-+      }
-+ol.menu a:hover {
-+      background:rgb(193,193,244);
-+      text-decoration:none;
-+      }
-+      
-+      
-+div.info {
-+      background:rgb(204,204,204);
-+      border:solid rgb(204,204,204) 1px;
-+      margin-bottom:1em;
-+      }
-+div.info h2 {
-+      background:rgb(204,204,204);
-+      color:black;
-+      font-size:1em;
-+      margin:0;
-+      padding:0.1em 1em 0.1em 1em;
-+      }
-+div.info table {
-+      border:solid rgb(204,204,204) 1px;
-+      border-spacing:0;
-+      width:100%;
-+      }
-+div.info table th {
-+      background:rgb(204,204,204);
-+      color:white;
-+      margin:0;
-+      padding:0.1em 1em 0.1em 1em;
-+      }
-+div.info table th a.sortable { color:black; }
-+div.info table tr.tr-0 { background:rgb(238,238,238); }
-+div.info table tr.tr-1 { background:rgb(221,221,221); }
-+div.info table td { padding:0.3em 1em 0.3em 1em; }
-+div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
-+div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
-+div.info table td h3 {
-+      color:black;
-+      font-size:1.1em;
-+      margin-left:-0.3em;
-+      }
++        if(h->opened_path) {
++            filename = h->opened_path;
++        } else {
++            filename = h->filename;
++        }
++        stream = php_stream_open_wrapper(filename, "rb", REPORT_ERRORS | ENFORCE_SAFE_MODE, NULL);
++        if(stream) {
++            PHP_MD5Init(&context);
++            while((n = php_stream_read(stream, (char*)buf, sizeof(buf))) > 0) {
++                PHP_MD5Update(&context, buf, n);
++            }
++            PHP_MD5Final(key.md5, &context);
++            php_stream_close(stream);
++            if(n<0) {
++                apc_wprint("Error while reading '%s' for md5 generation.", filename);
++            }
++        } else {
++            apc_wprint("Unable to open '%s' for md5 generation.", filename);
++        }
++    }
 +
-+div.graph { margin-bottom:1em }
-+div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
-+div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
-+div.graph table td.td-0 { background:rgb(238,238,238); }
-+div.graph table td.td-1 { background:rgb(221,221,221); }
-+div.graph table td { padding:0.2em 1em 0.4em 1em; }
++    if(!(alloc_op_array = apc_copy_op_array(NULL, *op_array, &ctxt TSRMLS_CC))) {
++        goto freepool;
++    }
 +
-+div.div1,div.div2 { margin-bottom:1em; width:35em; }
-+div.div3 { position:absolute; left:40em; top:1em; width:580px; }
-+//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
++    if(!(alloc_functions = apc_copy_new_functions(num_functions, &ctxt TSRMLS_CC))) {
++        goto freepool;
++    }
++    if(!(alloc_classes = apc_copy_new_classes(*op_array, num_classes, &ctxt TSRMLS_CC))) {
++        goto freepool;
++    }
 +
-+div.sorting { margin:1.5em 0em 1.5em 2em }
-+.center { text-align:center }
-+.aright { position:absolute;right:1em }
-+.right { text-align:right }
-+.ok { color:rgb(0,200,0); font-weight:bold}
-+.failed { color:rgb(200,0,0); font-weight:bold}
++    path = h->opened_path;
++    if(!path) path=h->filename;
 +
-+span.box {
-+      border: black solid 1px;
-+      border-right:solid black 2px;
-+      border-bottom:solid black 2px;
-+      padding:0 0.5em 0 0.5em;
-+      margin-right:1em;
-+}
-+span.green { background:#60F060; padding:0 0.5em 0 0.5em}
-+span.red { background:#D06030; padding:0 0.5em 0 0.5em }
++#ifdef __DEBUG_APC__
++    fprintf(stderr,"2. h->opened_path=[%s]  h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
++#endif
 +
-+div.authneeded {
-+      background:rgb(238,238,238);
-+      border:solid rgb(204,204,204) 1px;
-+      color:rgb(200,0,0);
-+      font-size:1.2em;
-+      font-weight:bold;
-+      padding:2em;
-+      text-align:center;
-+      }
-+      
-+input {
-+      background:rgb(153,153,204);
-+      border:solid rgb(102,102,153) 2px;
-+      color:white;
-+      font-weight:bold;
-+      margin-right:1em;
-+      padding:0.1em 0.5em 0.1em 0.5em;
-+      }
-+//-->
-+</style>
-+</head>
-+<body>
-+<div class="head">
-+      <h1 class="apc">
-+              <div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APC">APC</a></span></div>
-+              <div class="nameinfo">Opcode Cache</div>
-+      </h1>
-+      <div class="login">
-+      <?php put_login_link(); ?>
-+      </div>
-+      <hr class="apc">
-+</div>
-+<?php
++    if(!(*cache_entry = apc_cache_make_file_entry(path, alloc_op_array, alloc_functions, alloc_classes, &ctxt))) {
++        goto freepool;
++    }
 +
++    return SUCCESS;
++
++freepool:
++    apc_pool_destroy(ctxt.pool);
++    ctxt.pool = NULL;
++
++    return FAILURE;
 +
-+// Display main Menu
-+echo <<<EOB
-+      <ol class=menu>
-+      <li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
-+EOB;
-+echo
-+      menu_entry(1,'View Host Stats'),
-+      menu_entry(2,'System Cache Entries');
-+if ($AUTHENTICATED) {
-+      echo menu_entry(4,'Per-Directory Entries');
-+}
-+echo
-+      menu_entry(3,'User Cache Entries'),
-+      menu_entry(9,'Version Check');
-+      
-+if ($AUTHENTICATED) {
-+      echo <<<EOB
-+              <li><a class="aright" href="$MY_SELF&CC=1&OB={$MYREQUEST['OB']}" onClick="javascipt:return confirm('Are you sure?');">Clear $cache_mode Cache</a></li>
-+EOB;
 +}
-+echo <<<EOB
-+      </ol>
-+EOB;
++/* }}} */
 +
++/* {{{ my_compile_file
++   Overrides zend_compile_file */
++static zend_op_array* my_compile_file(zend_file_handle* h,
++                                               int type TSRMLS_DC)
++{
++    apc_cache_key_t key;
++    apc_cache_entry_t* cache_entry;
++    zend_op_array* op_array = NULL;
++    time_t t;
++    apc_context_t ctxt = {0,};
++    int bailout=0;
 +
-+// CONTENT
-+echo <<<EOB
-+      <div class=content>
-+EOB;
++    if (!APCG(enabled) || apc_cache_busy(apc_cache)) {
++        return old_compile_file(h, type TSRMLS_CC);
++    }
 +
-+// MAIN SWITCH STATEMENT 
++    /* check our regular expression filters */
++    if (APCG(filters) && APCG(compiled_filters) && h->opened_path) {
++        int ret = apc_regex_match_array(APCG(compiled_filters), h->opened_path);
 +
-+switch ($MYREQUEST['OB']) {
++        if(ret == APC_NEGATIVE_MATCH || (ret != APC_POSITIVE_MATCH && !APCG(cache_by_default))) {
++            return old_compile_file(h, type TSRMLS_CC);
++        }
++    } else if(!APCG(cache_by_default)) {
++        return old_compile_file(h, type TSRMLS_CC);
++    }
++    APCG(current_cache) = apc_cache;
 +
 +
++    t = apc_time();
 +
++#ifdef __DEBUG_APC__
++    fprintf(stderr,"1. h->opened_path=[%s]  h->filename=[%s]\n", h->opened_path?h->opened_path:"null",h->filename);
++#endif
 +
++    /* try to create a cache key; if we fail, give up on caching */
++    if (!apc_cache_make_file_key(&key, h->filename, PG(include_path), t TSRMLS_CC)) {
++        return old_compile_file(h, type TSRMLS_CC);
++    }
 +
-+// -----------------------------------------------
-+// Host Stats
-+// -----------------------------------------------
-+case OB_HOST_STATS:
-+      $mem_size = $mem['num_seg']*$mem['seg_size'];
-+      $mem_avail= $mem['avail_mem'];
-+      $mem_used = $mem_size-$mem_avail;
-+      $seg_size = bsize($mem['seg_size']);
-+      $req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']));
-+      $hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time']));
-+      $miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time']));
-+      $insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time']));
-+      $req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time']));
-+      $hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time']));
-+      $miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time']));
-+      $insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time']));
-+      $apcversion = phpversion('apc');
-+      $phpversion = phpversion();
-+      $number_files = $cache['num_entries']; 
-+    $size_files = bsize($cache['mem_size']);
-+      $number_vars = $cache_user['num_entries'];
-+    $size_vars = bsize($cache_user['mem_size']);
-+      $i=0;
-+      echo <<< EOB
-+              <div class="info div1"><h2>General Cache Information</h2>
-+              <table cellspacing=0><tbody>
-+              <tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr>
-+              <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
-+EOB;
 +
-+      if(!empty($_SERVER['SERVER_NAME']))
-+              echo "<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
-+      if(!empty($_SERVER['SERVER_SOFTWARE']))
-+              echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
++    if(!APCG(force_file_update)) {
++        /* search for the file in the cache */
++        cache_entry = apc_cache_find(apc_cache, key, t);
++        ctxt.force_update = 0;
++    } else {
++        cache_entry = NULL;
++        ctxt.force_update = 1;
++    }
 +
-+      echo <<<EOB
-+              <tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size 
-+    <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking)
-+    </td></tr>
-+EOB;
-+      echo   '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>';
-+      echo   '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>';
-+      echo   '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>';
-+      echo <<<EOB
-+              </tbody></table>
-+              </div>
++    if (cache_entry != NULL) {
++        int dummy = 1;
 +
-+              <div class="info div1"><h2>File Cache Information</h2>
-+              <table cellspacing=0><tbody>
-+              <tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr>
-+              <tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
-+              <tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
-+              <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>
-+              <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>
-+              <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>
-+              <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr>
-+              <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
-+              </tbody></table>
-+              </div>
++        ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free,
++                                                apc_sma_protect, apc_sma_unprotect);
++        if (!ctxt.pool) {
++            apc_wprint("Unable to allocate memory for pool.");
++            return old_compile_file(h, type TSRMLS_CC);
++        }
++        ctxt.copy = APC_COPY_OUT_OPCODE;
 +
-+              <div class="info div1"><h2>User Cache Information</h2>
-+              <table cellspacing=0><tbody>
-+    <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
-+              <tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr>
-+              <tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr>
-+              <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
-+              <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
-+              <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
-+              <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
-+              <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr>
++        if (h->opened_path == NULL) {
++            h->opened_path = estrdup(cache_entry->data.file.filename);
++        }
++        zend_hash_add(&EG(included_files), h->opened_path, strlen(h->opened_path)+1, (void *)&dummy, sizeof(int), NULL);
 +
-+              </tbody></table>
-+              </div>
++        zend_llist_add_element(&CG(open_files), h); /* We leak fds without this hack */
 +
-+              <div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
-+EOB;
++        apc_stack_push(APCG(cache_stack), cache_entry);
++        op_array = cached_compile(h, type, &ctxt TSRMLS_CC);
++        if(op_array) {
++#ifdef APC_FILEHITS
++            /* If the file comes from the cache, add it to the global request file list */
++            add_next_index_string(APCG(filehits), h->filename, 1);
++#endif
++            /* this is an unpool, which has no cleanup - this only free's the pool header */
++            apc_pool_destroy(ctxt.pool);
++            return op_array;
++        }
++        if(APCG(report_autofilter)) {
++            apc_wprint("Recompiling %s", cache_entry->data.file.filename);
++        }
++        /* TODO: check what happens with EG(included_files) */
++    }
 +
-+      $j = 0;
-+      foreach (ini_get_all('apc') as $k => $v) {
-+              echo "<tr class=tr-$j><td class=td-0>",$k,"</td><td>",str_replace(',',',<br />',$v['local_value']),"</td></tr>\n";
-+              $j = 1 - $j;
-+      }
++    /* Make sure the mtime reflects the files last known mtime in the case of fpstat==0 */
++    if(key.type == APC_CACHE_KEY_FPFILE) {
++        apc_fileinfo_t fileinfo;
++        struct stat *tmp_buf = NULL;
++        if(!strcmp(SG(request_info).path_translated, h->filename)) {
++            tmp_buf = sapi_get_stat(TSRMLS_C);  /* Apache has already done this stat() for us */
++        }
++        if(tmp_buf) {
++            fileinfo.st_buf.sb = *tmp_buf;
++        } else {
++            if (apc_search_paths(h->filename, PG(include_path), &fileinfo) != 0) {
++#ifdef __DEBUG_APC__
++                fprintf(stderr,"Stat failed %s - bailing (%s) (%d)\n",h->filename,SG(request_info).path_translated);
++#endif
++                return op_array;
++            }
++        }
++        key.mtime = fileinfo.st_buf.sb.st_mtime;
++    }
 +
-+      if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1)
-+              $mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
-+      else
-+              $mem_note = "Memory Usage";
++    HANDLE_BLOCK_INTERRUPTIONS();
 +
-+      echo <<< EOB
-+              </tbody></table>
-+              </div>
++#if NONBLOCKING_LOCK_AVAILABLE
++    if(APCG(write_lock)) {
++        if(!apc_cache_write_lock(apc_cache)) {
++            HANDLE_UNBLOCK_INTERRUPTIONS();
++            return old_compile_file(h, type TSRMLS_CC);
++        }
++    }
++#endif
 +
-+              <div class="graph div3"><h2>Host Status Diagrams</h2>
-+              <table cellspacing=0><tbody>
-+EOB;
-+      $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
-+      echo <<<EOB
-+              <tr>
-+              <td class=td-0>$mem_note</td>
-+              <td class=td-1>Hits &amp; Misses</td>
-+              </tr>
-+EOB;
++    zend_try {
++        if (apc_compile_cache_entry(key, h, type, t, &op_array, &cache_entry TSRMLS_CC) == SUCCESS) {
++            ctxt.pool = cache_entry->pool;
++            ctxt.copy = APC_COPY_IN_OPCODE;
++            if (apc_cache_insert(apc_cache, key, cache_entry, &ctxt, t) != 1) {
++                apc_pool_destroy(ctxt.pool);
++                ctxt.pool = NULL;
++            }
++        }
++    } zend_catch {
++        bailout=1; /* in the event of a bailout, ensure we don't create a dead-lock */
++    } zend_end_try();
 +
-+      echo
-+              graphics_avail() ? 
-+                        '<tr>'.
-+                        "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF?IMG=1&$time\"></td>".
-+                        "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF?IMG=2&$time\"></td></tr>\n"
-+                      : "",
-+              '<tr>',
-+              '<td class=td-0><span class="green box">&nbsp;</span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
-+              '<td class=td-1><span class="green box">&nbsp;</span>Hits: ',$cache['num_hits'].sprintf(" (%.1f%%)",$cache['num_hits']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n",
-+              '</tr>',
-+              '<tr>',
-+              '<td class=td-0><span class="red box">&nbsp;</span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
-+              '<td class=td-1><span class="red box">&nbsp;</span>Misses: ',$cache['num_misses'].sprintf(" (%.1f%%)",$cache['num_misses']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n";
-+      echo <<< EOB
-+              </tr>
-+              </tbody></table>
++    APCG(current_cache) = NULL;
 +
-+              <br/>
-+              <h2>Detailed Memory Usage and Fragmentation</h2>
-+              <table cellspacing=0><tbody>
-+              <tr>
-+              <td class=td-0 colspan=2><br/>
-+EOB;
++#if NONBLOCKING_LOCK_AVAILABLE
++    if(APCG(write_lock)) {
++        apc_cache_write_unlock(apc_cache);
++    }
++#endif
++    HANDLE_UNBLOCK_INTERRUPTIONS();
 +
-+      // Fragementation: (freeseg - 1) / total_seg
-+      $nseg = $freeseg = $fragsize = $freetotal = 0;
-+      for($i=0; $i<$mem['num_seg']; $i++) {
-+              $ptr = 0;
-+              foreach($mem['block_lists'][$i] as $block) {
-+                      if ($block['offset'] != $ptr) {
-+                              ++$nseg;
-+                      }
-+                      $ptr = $block['offset'] + $block['size'];
-+                        /* Only consider blocks <5M for the fragmentation % */
-+                        if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];
-+                        $freetotal+=$block['size'];
-+              }
-+              $freeseg += count($mem['block_lists'][$i]);
-+      }
-+      
-+      if ($freeseg > 1) {
-+              $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);
-+      } else {
-+              $frag = "0%";
-+      }
++    if (bailout) zend_bailout();
 +
-+      if (graphics_avail()) {
-+              $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);
-+              echo <<<EOB
-+                      <img alt="" $size src="$PHP_SELF?IMG=3&$time">
-+EOB;
-+      }
-+      echo <<<EOB
-+              </br>Fragmentation: $frag
-+              </td>
-+              </tr>
-+EOB;
-+        if(isset($mem['adist'])) {
-+          foreach($mem['adist'] as $i=>$v) {
-+            $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;
-+            if($i==0) $range = "1";
-+            else $range = "$cur - $nxt";
-+            echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
-+          }
-+        }
-+        echo <<<EOB
-+              </tbody></table>
-+              </div>
-+EOB;
-+              
-+      break;
++    return op_array;
++}
++/* }}} */
 +
++/* {{{ data preload */
 +
-+// -----------------------------------------------
-+// User Cache Entries
-+// -----------------------------------------------
-+case OB_USER_CACHE:
-+      if (!$AUTHENTICATED) {
-+              echo '<div class="authneeded">You need to login to see the user values here!<br/>&nbsp;<br/>';
-+              put_login_link("Login now!");
-+              echo '</div>';
-+              break;
-+      }
-+      $fieldname='info';
-+      $fieldheading='User Entry Label';
-+      $fieldkey='info';
++extern int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC);
 +
-+// -----------------------------------------------
-+// System Cache Entries               
-+// -----------------------------------------------
-+case OB_SYS_CACHE:    
-+      if (!isset($fieldname))
-+      {
-+              $fieldname='filename';
-+              $fieldheading='Script Filename';
-+              if(ini_get("apc.stat")) $fieldkey='inode';
-+              else $fieldkey='filename'; 
-+      }
-+      if (!empty($MYREQUEST['SH']))
-+      {
-+              echo <<< EOB
-+                      <div class="info"><table cellspacing=0><tbody>
-+                      <tr><th>Attribute</th><th>Value</th></tr>
-+EOB;
++static zval* data_unserialize(const char *filename)
++{
++    zval* retval;
++    long len = 0;
++    struct stat sb;
++    char *contents, *tmp;
++    FILE *fp;
++    php_unserialize_data_t var_hash;
++    TSRMLS_FETCH();
 +
-+              $m=0;
-+              foreach($scope_list as $j => $list) {
-+                      foreach($cache[$list] as $i => $entry) {
-+                              if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue;
-+                              foreach($entry as $k => $value) {
-+                                      if (!$AUTHENTICATED) {
-+                                              // hide all path entries if not logged in
-+                                              $value=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$value);
-+                                      }
-+
-+                                      if ($k == "num_hits") {
-+                                              $value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']);
-+                                      }
-+                                      if ($k == 'deletion_time') {
-+                                              if(!$entry['deletion_time']) $value = "None";
-+                                      }
-+                                      echo
-+                                              "<tr class=tr-$m>",
-+                                              "<td class=td-0>",ucwords(preg_replace("/_/"," ",$k)),"</td>",
-+                                              "<td class=td-last>",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : $value,"</td>",
-+                                              "</tr>";
-+                                      $m=1-$m;
-+                              }
-+                              if($fieldkey=='info') {
-+                                      echo "<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>";
-+                                      $output = var_export(apc_fetch($entry[$fieldkey]),true);
-+                                      echo htmlspecialchars($output);
-+                                      echo "</pre></td></tr>\n";
-+                              }
-+                              break;
-+                      }
-+              }
++    if(VCWD_STAT(filename, &sb) == -1) {
++        return NULL;
++    }
 +
-+              echo <<<EOB
-+                      </tbody></table>
-+                      </div>
-+EOB;
-+              break;
-+      }
++    fp = fopen(filename, "rb");
 +
-+      $cols=6;
-+      echo <<<EOB
-+              <div class=sorting><form>Scope:
-+              <input type=hidden name=OB value={$MYREQUEST['OB']}>
-+              <select name=SCOPE>
-+EOB;
-+      echo 
-+              "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
-+              "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
-+              "</select>",
-+              ", Sorting:<select name=SORT1>",
-+              "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Hits</option>",
-+              "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Size</option>",
-+              "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">$fieldheading</option>",
-+              "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Last accessed</option>",
-+              "<option value=M",$MYREQUEST['SORT1']=='M' ? " selected":"",">Last modified</option>",
-+              "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Created at</option>",
-+              "<option value=D",$MYREQUEST['SORT1']=='D' ? " selected":"",">Deleted at</option>";
-+      if($fieldname=='info') echo
-+              "<option value=D",$MYREQUEST['SORT1']=='T' ? " selected":"",">Timeout</option>";
-+      echo 
-+              '</select>',
-+              '<select name=SORT2>',
-+              '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
-+              '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
-+              '</select>',
-+              '<select name=COUNT onChange="form.submit()">',
-+              '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
-+              '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
-+              '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
-+              '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
-+              '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
-+              '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
-+              '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
-+              '<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
-+              '</select>',
-+    '&nbsp; Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>',
-+              '&nbsp;<input type=submit value="GO!">',
-+              '</form></div>',
++    len = sizeof(char)*sb.st_size;
 +
-+              '<div class="info"><table cellspacing=0><tbody>',
-+              '<tr>',
-+              '<th>',sortheader('S',$fieldheading,  "&OB=".$MYREQUEST['OB']),'</th>',
-+              '<th>',sortheader('H','Hits',         "&OB=".$MYREQUEST['OB']),'</th>',
-+              '<th>',sortheader('Z','Size',         "&OB=".$MYREQUEST['OB']),'</th>',
-+              '<th>',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'</th>',
-+              '<th>',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'</th>',
-+              '<th>',sortheader('C','Created at',   "&OB=".$MYREQUEST['OB']),'</th>';
++    tmp = contents = malloc(len);
 +
-+      if($fieldname=='info') {
-+              $cols+=2;
-+               echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>';
-+      }
-+      echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>';
++    if(!contents) {
++       return NULL;
++    }
 +
-+      // builds list with alpha numeric sortable keys
-+      //
-+      $list = array();
-+      foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {
-+              switch($MYREQUEST['SORT1']) {
-+                      case 'A': $k=sprintf('%015d-',$entry['access_time']);   break;
-+                      case 'H': $k=sprintf('%015d-',$entry['num_hits']);              break;
-+                      case 'Z': $k=sprintf('%015d-',$entry['mem_size']);              break;
-+                      case 'M': $k=sprintf('%015d-',$entry['mtime']);                 break;
-+                      case 'C': $k=sprintf('%015d-',$entry['creation_time']); break;
-+                      case 'T': $k=sprintf('%015d-',$entry['ttl']);                   break;
-+                      case 'D': $k=sprintf('%015d-',$entry['deletion_time']); break;
-+                      case 'S': $k='';                                                                                break;
-+              }
-+              if (!$AUTHENTICATED) {
-+                      // hide all path entries if not logged in
-+                      $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$entry);
-+              } else {
-+                      $list[$k.$entry[$fieldname]]=$entry;
-+              }
-+      }
++    if(fread(contents, 1, len, fp) < 1) {     
++      free(contents);
++      return NULL;
++    }
 +
-+      if ($list) {
-+              
-+              // sort list
-+              //
-+              switch ($MYREQUEST['SORT2']) {
-+                      case "A":       krsort($list);  break;
-+                      case "D":       ksort($list);   break;
-+              }
-+              
-+              // output list
-+              $i=0;
-+              foreach($list as $k => $entry) {
-+      if(!$MYREQUEST['SEARCH'] || preg_match('/'.$MYREQUEST['SEARCH'].'/i', $entry[$fieldname]) != 0) {  
-+        echo
-+          '<tr class=tr-',$i%2,'>',
-+          "<td class=td-0><a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&SH=",md5($entry[$fieldkey]),"\">",$entry[$fieldname],'</a></td>',
-+          '<td class="td-n center">',$entry['num_hits'],'</td>',
-+          '<td class="td-n right">',$entry['mem_size'],'</td>',
-+          '<td class="td-n center">',date(DATE_FORMAT,$entry['access_time']),'</td>',
-+          '<td class="td-n center">',date(DATE_FORMAT,$entry['mtime']),'</td>',
-+          '<td class="td-n center">',date(DATE_FORMAT,$entry['creation_time']),'</td>';
++    MAKE_STD_ZVAL(retval);
 +
-+        if($fieldname=='info') {
-+          if($entry['ttl'])
-+            echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>';
-+          else
-+            echo '<td class="td-n center">None</td>';
-+        }
-+        if ($entry['deletion_time']) {
++    PHP_VAR_UNSERIALIZE_INIT(var_hash);
++    
++    /* I wish I could use json */
++    if(!php_var_unserialize(&retval, (const unsigned char**)&tmp, (const unsigned char*)(contents+len), &var_hash TSRMLS_CC)) {
++        zval_ptr_dtor(&retval);
++        return NULL;
++    }
 +
-+          echo '<td class="td-last center">', date(DATE_FORMAT,$entry['deletion_time']), '</td>';
-+        } else if ($MYREQUEST['OB'] == OB_USER_CACHE) {
++    PHP_VAR_UNSERIALIZE_DESTROY(var_hash);
 +
-+          echo '<td class="td-last center">';
-+          echo '[<a href="', $MY_SELF, '&OB=', $MYREQUEST['OB'], '&DU=', urlencode($entry[$fieldkey]), '">Delete Now</a>]';
-+          echo '</td>';
-+        } else {
-+          echo '<td class="td-last center"> &nbsp; </td>';
-+        }
-+        echo '</tr>';
-+        $i++;
-+        if ($i == $MYREQUEST['COUNT'])
-+          break;
-+      }
-+              }
-+              
-+      } else {
-+              echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>';
-+      }
-+      echo <<< EOB
-+              </tbody></table>
-+EOB;
++    free(contents);
++    fclose(fp);
 +
-+      if ($list && $i < count($list)) {
-+              echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
-+      }
++    return retval;
++}
 +
-+      echo <<< EOB
-+              </div>
-+EOB;
-+      break;
++static int apc_load_data(const char *data_file TSRMLS_DC)
++{
++    char *p;
++    char key[MAXPATHLEN] = {0,};
++    unsigned int key_len;
++    zval *data;
 +
++    p = strrchr(data_file, DEFAULT_SLASH);
 +
-+// -----------------------------------------------
-+// Per-Directory System Cache Entries
-+// -----------------------------------------------
-+case OB_SYS_CACHE_DIR:        
-+      if (!$AUTHENTICATED) {
-+              break;
-+      }
++    if(p && p[1]) {
++        strlcpy(key, p+1, sizeof(key));
++        p = strrchr(key, '.');
 +
-+      echo <<<EOB
-+              <div class=sorting><form>Scope:
-+              <input type=hidden name=OB value={$MYREQUEST['OB']}>
-+              <select name=SCOPE>
-+EOB;
-+      echo 
-+              "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
-+              "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
-+              "</select>",
-+              ", Sorting:<select name=SORT1>",
-+              "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Total Hits</option>",
-+              "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Total Size</option>",
-+              "<option value=T",$MYREQUEST['SORT1']=='T' ? " selected":"",">Number of Files</option>",
-+              "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">Directory Name</option>",
-+              "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Avg. Size</option>",
-+              "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Avg. Hits</option>",
-+              '</select>',
-+              '<select name=SORT2>',
-+              '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
-+              '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
-+              '</select>',
-+              '<select name=COUNT onChange="form.submit()">',
-+              '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
-+              '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
-+              '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
-+              '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
-+              '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
-+              '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
-+              '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
-+              '<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
-+              '</select>',
-+              ", Group By Dir Level:<select name=AGGR>",
-+              "<option value='' selected>None</option>";
-+              for ($i = 1; $i < 10; $i++)
-+                      echo "<option value=$i",$MYREQUEST['AGGR']==$i ? " selected":"",">$i</option>";
-+              echo '</select>',
-+              '&nbsp;<input type=submit value="GO!">',
-+              '</form></div>',
++        if(p) {
++            p[0] = '\0';
++            key_len = strlen(key);
 +
-+              '<div class="info"><table cellspacing=0><tbody>',
-+              '<tr>',
-+              '<th>',sortheader('S','Directory Name', "&OB=".$MYREQUEST['OB']),'</th>',
-+              '<th>',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'</th>',
-+              '<th>',sortheader('H','Total Hits',     "&OB=".$MYREQUEST['OB']),'</th>',
-+              '<th>',sortheader('Z','Total Size',     "&OB=".$MYREQUEST['OB']),'</th>',
-+              '<th>',sortheader('C','Avg. Hits',      "&OB=".$MYREQUEST['OB']),'</th>',
-+              '<th>',sortheader('A','Avg. Size',      "&OB=".$MYREQUEST['OB']),'</th>',
-+              '</tr>';
++            data = data_unserialize(data_file);
++            if(data) {
++                _apc_store(key, key_len, data, 0, 1 TSRMLS_CC);
++            }
++            return 1;
++        }
++    }
 +
-+      // builds list with alpha numeric sortable keys
-+      //
-+      $tmp = $list = array();
-+      foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) {
-+              $n = dirname($entry['filename']);
-+              if ($MYREQUEST['AGGR'] > 0) {
-+                      $n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n);
-+              }
-+              if (!isset($tmp[$n])) {
-+                      $tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);
-+              }
-+              $tmp[$n]['hits'] += $entry['num_hits'];
-+              $tmp[$n]['size'] += $entry['mem_size'];
-+              ++$tmp[$n]['ents'];
-+      }
++    return 0;
++}
 +
-+      foreach ($tmp as $k => $v) {
-+              switch($MYREQUEST['SORT1']) {
-+                      case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break;
-+                      case 'T': $kn=sprintf('%015d-',$v['ents']);             break;
-+                      case 'H': $kn=sprintf('%015d-',$v['hits']);             break;
-+                      case 'Z': $kn=sprintf('%015d-',$v['size']);             break;
-+                      case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break;
-+                      case 'S': $kn = $k;                                     break;
-+              }
-+              $list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);
-+      }
++static int apc_walk_dir(const char *path TSRMLS_DC)
++{
++    char file[MAXPATHLEN]={0,};
++    int ndir, i;
++    char *p = NULL;
++    struct dirent **namelist = NULL;
 +
-+      if ($list) {
-+              
-+              // sort list
-+              //
-+              switch ($MYREQUEST['SORT2']) {
-+                      case "A":       krsort($list);  break;
-+                      case "D":       ksort($list);   break;
-+              }
-+              
-+              // output list
-+              $i = 0;
-+              foreach($list as $entry) {
-+                      echo
-+                              '<tr class=tr-',$i%2,'>',
-+                              "<td class=td-0>",$entry[0],'</a></td>',
-+                              '<td class="td-n center">',$entry[1],'</td>',
-+                              '<td class="td-n center">',$entry[2],'</td>',
-+                              '<td class="td-n center">',$entry[3],'</td>',
-+                              '<td class="td-n center">',round($entry[2] / $entry[1]),'</td>',
-+                              '<td class="td-n center">',round($entry[3] / $entry[1]),'</td>',
-+                              '</tr>';
++    if ((ndir = php_scandir(path, &namelist, 0, php_alphasort)) > 0)
++    {
++        for (i = 0; i < ndir; i++)
++        {
++            /* check for extension */
++            if (!(p = strrchr(namelist[i]->d_name, '.'))
++                    || (p && strcmp(p, ".data")))
++            {
++                free(namelist[i]);
++                continue;
++            }
++            snprintf(file, MAXPATHLEN, "%s%c%s",
++                    path, DEFAULT_SLASH, namelist[i]->d_name);
++            if(!apc_load_data(file TSRMLS_CC))
++            {
++                /* print error */
++            }
++            free(namelist[i]);
++        }
++        free(namelist);
++    }
 +
-+                      if (++$i == $MYREQUEST['COUNT']) break;
-+              }
-+              
-+      } else {
-+              echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>';
-+      }
-+      echo <<< EOB
-+              </tbody></table>
-+EOB;
++    return 1;
++}
 +
-+      if ($list && $i < count($list)) {
-+              echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
-+      }
++void apc_data_preload(TSRMLS_D)
++{
++    if(!APCG(preload_path)) return;
 +
-+      echo <<< EOB
-+              </div>
-+EOB;
-+      break;
++    apc_walk_dir(APCG(preload_path) TSRMLS_CC);
++}
++/* }}} */
 +
-+// -----------------------------------------------
-+// Version check
-+// -----------------------------------------------
-+case OB_VERSION_CHECK:
-+      echo <<<EOB
-+              <div class="info"><h2>APC Version Information</h2>
-+              <table cellspacing=0><tbody>
-+              <tr>
-+              <th></th>
-+              </tr>
-+EOB;
++/* {{{ module init and shutdown */
 +
-+      $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss");
-+      if (!$rss) {
-+              echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
-+      } else {
-+              $apcversion = phpversion('apc');
++int apc_module_init(int module_number TSRMLS_DC)
++{
++    /* apc initialization */
++#if APC_MMAP
++    apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, APCG(mmap_file_mask));
++#else
++    apc_sma_init(APCG(shm_segments), APCG(shm_size)*1024*1024, NULL);
++#endif
++    apc_cache = apc_cache_create(APCG(num_files_hint), APCG(gc_ttl), APCG(ttl));
++    apc_user_cache = apc_cache_create(APCG(user_entries_hint), APCG(gc_ttl), APCG(user_ttl));
 +
-+              preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);
-+              echo '<tr class="tr-0 center"><td>';
-+              if (version_compare($apcversion, $match[1], '>=')) {
-+                      echo '<div class="ok">You are running the latest version of APC ('.$apcversion.')</div>';
-+                      $i = 3;
-+              } else {
-+                      echo '<div class="failed">You are running an older version of APC ('.$apcversion.'), 
-+                              newer version '.$match[1].' is available at <a href="http://pecl.php.net/package/APC/'.$match[1].'">
-+                              http://pecl.php.net/package/APC/'.$match[1].'</a>
-+                              </div>';
-+                      $i = -1;
-+              }
-+              echo '</td></tr>';
-+              echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
++    /* override compilation */
++    old_compile_file = zend_compile_file;
++    zend_compile_file = my_compile_file;
++    REGISTER_LONG_CONSTANT("\000apc_magic", (long)&set_compile_hook, CONST_PERSISTENT | CONST_CS);
++    REGISTER_LONG_CONSTANT("\000apc_compile_file", (long)&my_compile_file, CONST_PERSISTENT | CONST_CS);
 +
-+              preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
-+              next($match[2]); next($match[2]);
++    apc_pool_init();
 +
-+              while (list(,$v) = each($match[2])) {
-+                      list(,$ver) = explode(' ', $v, 2);
-+                      if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
-+                              break;
-+                      } else if (!$i--) {
-+                              break;
-+                      }
-+                      echo "<b><a href=\"http://pecl.php.net/package/APC/$ver\">".htmlspecialchars($v)."</a></b><br><blockquote>";
-+                      echo nl2br(htmlspecialchars(current($match[2])))."</blockquote>";
-+                      next($match[2]);
-+              }
-+              echo '</td></tr>';
-+      }
-+      echo <<< EOB
-+              </tbody></table>
-+              </div>
-+EOB;
-+      break;
++    apc_data_preload(TSRMLS_C);
++
++#if APC_HAVE_LOOKUP_HOOKS
++    if(APCG(lazy_functions)) {
++        zend_set_lookup_function_hook(apc_lookup_function_hook TSRMLS_CC);
++        zend_set_defined_function_hook(apc_defined_function_hook TSRMLS_CC);
++    }
++    if(APCG(lazy_classes)) {
++        zend_set_lookup_class_hook(apc_lookup_class_hook TSRMLS_CC);
++        zend_set_declared_class_hook(apc_declared_class_hook TSRMLS_CC);
++    }
++#else
++    if(APCG(lazy_functions) || APCG(lazy_classes)) {
++        apc_wprint("Lazy function/class loading not available with this version of PHP, please disable APC lazy loading.");
++        APCG(lazy_functions) = APCG(lazy_classes) = 0;
++    }
++#endif
 +
++    APCG(initialized) = 1;
++    return 0;
 +}
 +
-+echo <<< EOB
-+      </div>
-+EOB;
++int apc_module_shutdown(TSRMLS_D)
++{
++    if (!APCG(initialized))
++        return 0;
 +
-+?>
++    /* restore compilation */
++    zend_compile_file = old_compile_file;
 +
-+<!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> -->
-+</body>
-+</html>
-diff -ubrN php-5.2.5-orig/ext/apc/apc_php.h php-5.2.5/ext/apc/apc_php.h
---- php-5.2.5-orig/ext/apc/apc_php.h   1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_php.h        2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,71 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          George Schlossnagle <george@omniti.com>                     |
-+  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
-+  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
-+  +----------------------------------------------------------------------+
++    /*
++     * In case we got interrupted by a SIGTERM or something else during execution
++     * we may have cache entries left on the stack that we need to check to make
++     * sure that any functions or classes these may have added to the global function
++     * and class tables are removed before we blow away the memory that hold them.
++     * 
++     * This is merely to remove memory leak warnings - as the process is terminated
++     * immediately after shutdown. The following while loop can be removed without
++     * affecting anything else.
++     */
++    while (apc_stack_size(APCG(cache_stack)) > 0) {
++        int i;
++        apc_cache_entry_t* cache_entry = (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
++        if (cache_entry->data.file.functions) {
++            for (i = 0; cache_entry->data.file.functions[i].function != NULL; i++) {
++                zend_hash_del(EG(function_table),
++                    cache_entry->data.file.functions[i].name,
++                    cache_entry->data.file.functions[i].name_len+1);
++            }
++        }
++        if (cache_entry->data.file.classes) {
++            for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
++                zend_hash_del(EG(class_table),
++                    cache_entry->data.file.classes[i].name,
++                    cache_entry->data.file.classes[i].name_len+1);
++            }
++        }
++        apc_cache_release(apc_cache, cache_entry);
++    }
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++    apc_cache_destroy(apc_cache);
++    apc_cache_destroy(apc_user_cache);
++    apc_sma_cleanup();
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++    APCG(initialized) = 0;
++    return 0;
++}
 +
-+ */
++/* }}} */
 +
-+/* $Id: apc_php.h,v 3.10 2006/11/16 20:24:48 gopalv Exp $ */
++/* {{{ process init and shutdown */
++int apc_process_init(int module_number TSRMLS_DC)
++{
++    return 0;
++}
 +
-+#ifndef APC_PHP_H
-+#define APC_PHP_H
++int apc_process_shutdown(TSRMLS_D)
++{
++    return 0;
++}
++/* }}} */
 +
-+/*
-+ * The purpose of this header file is to include all PHP and Zend headers that
-+ * are typically needed elsewhere in APC. This makes it easy to insure that
-+ * all required headers are available.
-+ */
 +
-+#include "php.h"
-+#include "zend.h"
-+#include "zend_API.h"
-+#include "zend_compile.h"
-+#include "zend_hash.h"
-+#include "zend_extensions.h"
++/* {{{ apc_deactivate */
++static void apc_deactivate(TSRMLS_D)
++{
++    /* The execution stack was unwound, which prevented us from decrementing
++     * the reference counts on active cache entries in `my_execute`.
++     */
++    while (apc_stack_size(APCG(cache_stack)) > 0) {
++        int i;
++        zend_class_entry* zce = NULL;
++        void ** centry = (void*)(&zce);
++        zend_class_entry** pzce = NULL;
 +
-+#if ZEND_MODULE_API_NO > 20050922
-+#define ZEND_ENGINE_2_2
-+#endif
-+#if ZEND_MODULE_API_NO > 20050921
-+#define ZEND_ENGINE_2_1
-+#endif
-+#ifdef ZEND_ENGINE_2_1
-+#include "zend_vm.h"
-+#endif
++        apc_cache_entry_t* cache_entry =
++            (apc_cache_entry_t*) apc_stack_pop(APCG(cache_stack));
 +
-+#include "rfc1867.h"
++        if (cache_entry->data.file.classes) {
++            for (i = 0; cache_entry->data.file.classes[i].class_entry != NULL; i++) {
++                centry = (void**)&pzce; /* a triple indirection to get zend_class_entry*** */
++                if(zend_hash_find(EG(class_table), 
++                    cache_entry->data.file.classes[i].name,
++                    cache_entry->data.file.classes[i].name_len+1,
++                    (void**)centry) == FAILURE)
++                {
++                    /* double inclusion of conditional classes ends up failing 
++                     * this lookup the second time around.
++                     */
++                    continue;
++                }
++
++                zce = *pzce;
++
++                zend_hash_del(EG(class_table),
++                    cache_entry->data.file.classes[i].name,
++                    cache_entry->data.file.classes[i].name_len+1);
++
++                apc_free_class_entry_after_execution(zce);
++            }
++        }
++        apc_cache_release(apc_cache, cache_entry);
++    }
++}
++/* }}} */
++
++/* {{{ request init and shutdown */
++
++int apc_request_init(TSRMLS_D)
++{
++    apc_stack_clear(APCG(cache_stack));
++    if (!APCG(compiled_filters) && APCG(filters)) {
++        /* compile regex filters here to avoid race condition between MINIT of PCRE and APC.
++         * This should be moved to apc_cache_create() if this race condition between modules is resolved */
++        APCG(compiled_filters) = apc_regex_compile_array(APCG(filters) TSRMLS_CC);
++    }
++
++    if(APCG(lazy_functions)) {
++        APCG(lazy_function_table) = emalloc(sizeof(HashTable));
++        zend_hash_init(APCG(lazy_function_table), 0, NULL, NULL, 0);
++    }
++    if(APCG(lazy_classes)) {
++        APCG(lazy_class_table) = emalloc(sizeof(HashTable));
++        zend_hash_init(APCG(lazy_class_table), 0, NULL, NULL, 0);
++    }
++
++#ifdef APC_FILEHITS
++    ALLOC_INIT_ZVAL(APCG(filehits));
++    array_init(APCG(filehits));
++#endif
++
++    return 0;
++}
++
++int apc_request_shutdown(TSRMLS_D)
++{
++
++    if(APCG(lazy_class_table)) {
++        zend_hash_destroy(APCG(lazy_class_table));
++        efree(APCG(lazy_class_table));
++    }
++    if(APCG(lazy_function_table)) {
++        zend_hash_destroy(APCG(lazy_function_table));
++        efree(APCG(lazy_function_table));
++    }
++
++    apc_deactivate(TSRMLS_C);
++
++#ifdef APC_FILEHITS
++    zval_ptr_dtor(&APCG(filehits));
++#endif
++
++    return 0;
++}
++
++/* }}} */
 +
-+#endif
 +
 +/*
 + * Local variables:
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_pthreadmutex.c php-5.2.5/ext/apc/apc_pthreadmutex.c
---- php-5.2.5-orig/ext/apc/apc_pthreadmutex.c  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_pthreadmutex.c       2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,111 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_main.h php-5.3.1/ext/apc/apc_main.h
+--- php-5.3.1.orig/ext/apc/apc_main.h  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_main.h       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,74 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -8347,92 +7846,55 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_pthreadmutex.c php-5.2.5/ext/apc/apc_pthre
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Brian Shire <shire@php.net>                                 |
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          George Schlossnagle <george@omniti.com>                     |
++  |          Rasmus Lerdorf <rasmus@php.net>                             |
++  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
++  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
 +  +----------------------------------------------------------------------+
 +
-+ */
-+
-+/* $Id: apc_pthreadmutex.c,v 3.3 2007/12/21 01:36:51 shire Exp $ */
-+
-+#include "apc_pthreadmutex.h"
-+
-+#ifdef APC_PTHREADMUTEX_LOCKS
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
 +
-+pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock) 
-+{ 
-+    int result;
-+    pthread_mutexattr_t* attr;
-+    attr = malloc(sizeof(pthread_mutexattr_t));
++   All other licensing and usage conditions are those of the PHP Group.
 +
-+    result = pthread_mutexattr_init(attr);
-+    if(result == ENOMEM) {
-+        apc_eprint("pthread mutex error: Insufficient memory exists to create the mutex attribute object.");
-+    } else if(result == EINVAL) {
-+        apc_eprint("pthread mutex error: attr does not point to writeable memory.");
-+    } else if(result == EFAULT) {
-+        apc_eprint("pthread mutex error: attr is an invalid pointer.");
-+    } 
++ */
 +
-+#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
-+       result = pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ADAPTIVE_NP);
-+       if (result == EINVAL) {
-+               apc_eprint("pthread_mutexattr_settype: unable to set adaptive mutexes");
-+       }
-+#endif
++/* $Id: apc_main.h 268255 2008-11-04 05:42:11Z rasmus $ */
 +
-+    /* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */
-+    result = pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED);
-+    if(result == EINVAL) {
-+        apc_eprint("pthread mutex error: attr is not an initialized mutex attribute object, or pshared is not a valid process-shared state setting.");
-+    } else if(result == EFAULT) {
-+        apc_eprint("pthread mutex error: attr is an invalid pointer.");
-+    } else if(result == ENOTSUP) {
-+        apc_eprint("pthread mutex error: pshared was set to PTHREAD_PROCESS_SHARED.");
-+    }
++#ifndef APC_MAIN_H
++#define APC_MAIN_H
 +
-+    if(pthread_mutex_init(lock, attr)) { 
-+        apc_eprint("unable to initialize pthread lock");
-+    }
-+    return lock;
-+}
++#include "apc_pool.h"
 +
-+void apc_pthreadmutex_destroy(pthread_mutex_t *lock)
-+{
-+    return; /* we don't actually destroy the mutex, as it would destroy it for all processes */
-+}
++/*
++ * This module provides the primary interface between PHP and APC.
++ */
 +
-+void apc_pthreadmutex_lock(pthread_mutex_t *lock)
-+{
-+    int result;
-+    result = pthread_mutex_lock(lock);
-+    if(result == EINVAL) {
-+        apc_eprint("unable to obtain pthread lock (EINVAL)");
-+    } else if(result == EDEADLK) {
-+        apc_eprint("unable to obtain pthread lock (EDEADLK)");
-+    }  
-+}
++extern int apc_module_init(int module_number TSRMLS_DC);
++extern int apc_module_shutdown(TSRMLS_D);
++extern int apc_process_init(int module_number TSRMLS_DC);
++extern int apc_process_shutdown(TSRMLS_D);
++extern int apc_request_init(TSRMLS_D);
++extern int apc_request_shutdown(TSRMLS_D);
 +
-+void apc_pthreadmutex_unlock(pthread_mutex_t *lock)
-+{
-+    if(pthread_mutex_unlock(lock)) {
-+        apc_eprint("unable to unlock pthread lock");
-+    }
-+}
++typedef enum _apc_copy_type {
++    APC_NO_COPY = 0,
++    APC_COPY_IN_OPCODE,
++    APC_COPY_OUT_OPCODE,
++    APC_COPY_IN_USER,
++    APC_COPY_OUT_USER
++} apc_copy_type;
 +
-+zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock)
++typedef struct _apc_context_t
 +{
-+    int rval;
-+    rval = pthread_mutex_trylock(lock);
-+    if(rval == EBUSY) {     /* Lock is already held */
-+        return 0;
-+    } else if(rval == 0) {  /* Obtained lock */
-+        return 1;
-+    } else {                /* Other error */
-+        apc_eprint("unable to obtain pthread trylock");
-+        return 0;
-+    }
-+}
-+
++    apc_pool *pool;
++    apc_copy_type copy;
++    unsigned int force_update:1;
++} apc_context_t;
 +
 +#endif
 +
@@ -8441,18 +7903,18 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_pthreadmutex.c php-5.2.5/ext/apc/apc_pthre
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_pthreadmutex.h php-5.2.5/ext/apc/apc_pthreadmutex.h
---- php-5.2.5-orig/ext/apc/apc_pthreadmutex.h  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_pthreadmutex.h       2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,48 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_mmap.c php-5.3.1/ext/apc/apc_mmap.c
+--- php-5.3.1.orig/ext/apc/apc_mmap.c  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_mmap.c       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,175 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -8462,30 +7924,157 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_pthreadmutex.h php-5.2.5/ext/apc/apc_pthre
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Brian Shire <shire@php.net>                                 |
++  | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
 +  +----------------------------------------------------------------------+
 +
-+ */
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
 +
-+/* $Id: apc_pthreadmutex.h,v 3.3 2007/01/28 07:53:57 shire Exp $ */
++   All other licensing and usage conditions are those of the PHP Group.
 +
-+#ifndef APC_PTHREADMUTEX_H
-+#define APC_PTHREADMUTEX_H
++ */
++
++/* $Id: apc_mmap.c 287248 2009-08-13 15:13:52Z gopalv $ */
 +
 +#include "apc.h"
++#include "apc_mmap.h"
++#include "apc_lock.h"
 +
-+#ifdef APC_PTHREADMUTEX_LOCKS 
++#if APC_MMAP
 +
-+#include <pthread.h>
++#include <fcntl.h>
++#include <sys/types.h>
++#include <sys/mman.h>
 +
-+pthread_mutex_t *apc_pthreadmutex_create();
-+void apc_pthreadmutex_destroy(pthread_mutex_t *lock);
-+void apc_pthreadmutex_lock(pthread_mutex_t *lock);
-+void apc_pthreadmutex_unlock(pthread_mutex_t *lock);
-+zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock);
++/*
++ * Some operating systems (like FreeBSD) have a MAP_NOSYNC flag that
++ * tells whatever update daemons might be running to not flush dirty
++ * vm pages to disk unless absolutely necessary.  My guess is that
++ * most systems that don't have this probably default to only synching
++ * to disk when absolutely necessary.
++ */
++#ifndef MAP_NOSYNC
++#define MAP_NOSYNC 0
++#endif
++
++/* support for systems where MAP_ANONYMOUS is defined but not MAP_ANON, ie: HP-UX bug #14615 */
++#if !defined(MAP_ANON) && defined(MAP_ANONYMOUS)
++# define MAP_ANON MAP_ANONYMOUS
++#endif
++
++apc_segment_t apc_mmap(char *file_mask, size_t size)
++{
++    apc_segment_t segment; 
++
++    int fd = -1;
++    int flags = MAP_SHARED | MAP_NOSYNC;
++    int remap = 1;
++
++    /* If no filename was provided, do an anonymous mmap */
++    if(!file_mask || (file_mask && !strlen(file_mask))) {
++#if !defined(MAP_ANON)
++        apc_eprint("Anonymous mmap does not apear to be available on this system (MAP_ANON/MAP_ANONYMOUS).  Please see the apc.mmap_file_mask INI option.");
++#else
++        fd = -1;
++        flags = MAP_SHARED | MAP_ANON;
++        remap = 0;
++#endif
++    } else if(!strcmp(file_mask,"/dev/zero")) { 
++        fd = open("/dev/zero", O_RDWR, S_IRUSR | S_IWUSR);
++        if(fd == -1) {
++            apc_eprint("apc_mmap: open on /dev/zero failed:");
++            goto error;
++        }
++        remap = 0; /* cannot remap */
++    } else if(strstr(file_mask,".shm")) {
++        /*
++         * If the filemask contains .shm we try to do a POSIX-compliant shared memory
++         * backed mmap which should avoid synchs on some platforms.  At least on
++         * FreeBSD this implies MAP_NOSYNC and on Linux it is equivalent of mmap'ing
++         * a file in a mounted shmfs.  For this to work on Linux you need to make sure
++         * you actually have shmfs mounted.  Also on Linux, make sure the file_mask you
++         * pass in has a leading / and no other /'s.  eg.  /apc.shm.XXXXXX
++         * On FreeBSD these are mapped onto the regular filesystem so you can put whatever
++         * path you want here.
++         */
++        if(!mktemp(file_mask)) {
++            apc_eprint("apc_mmap: mktemp on %s failed:", file_mask);
++            goto error;
++        }
++        fd = shm_open(file_mask, O_CREAT|O_RDWR, S_IRUSR|S_IWUSR);
++        if(fd == -1) {
++            apc_eprint("apc_mmap: shm_open on %s failed:", file_mask);
++            goto error;
++        }
++        if (ftruncate(fd, size) < 0) {
++            close(fd);
++            shm_unlink(file_mask);
++            apc_eprint("apc_mmap: ftruncate failed:");
++            goto error;
++        }
++        shm_unlink(file_mask);
++    } else {
++        /*
++         * Otherwise we do a normal filesystem mmap
++         */
++        fd = mkstemp(file_mask);
++        if(fd == -1) {
++            apc_eprint("apc_mmap: mkstemp on %s failed:", file_mask);
++            goto error;
++        }
++        if (ftruncate(fd, size) < 0) {
++            close(fd);
++            unlink(file_mask);
++            apc_eprint("apc_mmap: ftruncate failed:");
++            goto error;
++        }
++        unlink(file_mask);
++    }
++
++    segment.shmaddr = (void *)mmap(NULL, size, PROT_READ | PROT_WRITE, flags, fd, 0);
++
++#ifdef APC_MEMPROTECT
++    if(remap) {
++        segment.roaddr = (void *)mmap(NULL, size, PROT_READ, flags, fd, 0);
++    } else {
++        segment.roaddr = NULL;
++    }
++#endif
++
++    if((long)segment.shmaddr == -1) {
++        apc_eprint("apc_mmap: mmap failed:");
++    }
++
++    if(fd != -1) close(fd);
++    
++    return segment;
++
++error:
++
++    segment.shmaddr = (void*)-1;
++#ifdef APC_MEMPROTECT
++    segment.roaddr = NULL;
++#endif
++    return segment;
++}
++
++void apc_unmap(apc_segment_t *segment)
++{
++    if (munmap(segment->shmaddr, segment->size) < 0) {
++        apc_wprint("apc_unmap: munmap failed:");
++    }
 +
++#ifdef APC_MEMPROTECT
++    if (segment->roaddr && munmap(segment->roaddr, segment->size) < 0) {
++        apc_wprint("apc_unmap: munmap failed:");
++    }
 +#endif
 +
++}
++
 +#endif
 +
 +/*
@@ -8493,18 +8082,18 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_pthreadmutex.h php-5.2.5/ext/apc/apc_pthre
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_rfc1867.c php-5.2.5/ext/apc/apc_rfc1867.c
---- php-5.2.5-orig/ext/apc/apc_rfc1867.c       1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_rfc1867.c    2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,195 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_mmap.h php-5.3.1/ext/apc/apc_mmap.h
+--- php-5.3.1.orig/ext/apc/apc_mmap.h  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_mmap.h       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,54 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2009 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -8514,7 +8103,7 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_rfc1867.c php-5.2.5/ext/apc/apc_rfc1867.c
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
++  | Authors: Gopal V <gopalv@php.net> 
 +  +----------------------------------------------------------------------+
 +
 +   This software was contributed to PHP by Community Connect Inc. in 2002
@@ -8527,183 +8116,43 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_rfc1867.c php-5.2.5/ext/apc/apc_rfc1867.c
 +
 + */
 +
-+/* $Id: apc_rfc1867.c,v 3.12 2007/10/18 20:37:20 rasmus Exp $*/
++/* $Id: apc_mmap.h 273456 2009-01-13 14:43:58Z gopalv $ */
++
++#ifndef APC_MMAP_H
++#define APC_MMAP_H
++
++#include <limits.h>
 +
 +#include "apc.h"
-+#include "apc_globals.h"
-+#include "rfc1867.h"
++#include "apc_sma.h"
 +
-+#ifdef PHP_WIN32
-+#include "win32/time.h"
++/* Wrapper functions for shared memory mapped files */
++
++#if APC_MMAP
++apc_segment_t apc_mmap(char *file_mask, size_t size);
++void apc_unmap(apc_segment_t* segment);
 +#endif
 +
-+#ifdef MULTIPART_EVENT_FORMDATA
-+extern int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC);
++#endif
 +
-+static double my_time() {
-+    struct timeval a;
-+    double t;
-+    gettimeofday(&a, NULL);
-+    t = a.tv_sec + (a.tv_usec/1000000.00);
-+    return t;
-+}
-+
-+void apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC) {
-+    static char tracking_key[64];
-+    static int  key_length = 0;
-+    static size_t content_length = 0;
-+    static char filename[128];
-+    static char name[64];
-+    static char *temp_filename=NULL;
-+    static int cancel_upload = 0;
-+    static double start_time;
-+    static size_t bytes_processed = 0;
-+    static size_t prev_bytes_processed = 0;
-+    static int update_freq = 0;
-+    static double rate;
-+    zval *track = NULL;
-+
-+      switch (event) {
-+              case MULTIPART_EVENT_START:
-+                      {
-+                multipart_event_start *data = (multipart_event_start *) event_data;
-+                content_length = data->content_length;
-+                *tracking_key = '\0';
-+                *name = '\0';
-+                cancel_upload = 0;
-+                temp_filename = NULL;
-+                *filename= '\0';
-+                key_length = 0;
-+                start_time = my_time();
-+                bytes_processed = 0;
-+                rate = 0;
-+                update_freq = APCG(rfc1867_freq);
-+                if(update_freq < 0) {  // frequency is a percentage, not bytes
-+                    update_freq = content_length * APCG(rfc1867_freq) / 100; 
-+                }
-+                      }
-+                      break;
-+
-+              case MULTIPART_EVENT_FORMDATA:
-+                      {
-+                int prefix_len = strlen(APCG(rfc1867_prefix));
-+                multipart_event_formdata *data = (multipart_event_formdata *) event_data;
-+                              if(data->name && !strncasecmp(data->name, APCG(rfc1867_name), strlen(APCG(rfc1867_name))) && data->value && data->length && data->length < sizeof(tracking_key) - prefix_len) {
-+                    strlcat(tracking_key, APCG(rfc1867_prefix), 63);
-+                    strlcat(tracking_key, *data->value, 63);
-+                    key_length = data->length + prefix_len;
-+                    bytes_processed = data->post_bytes_processed;
-+                              }
-+                      }
-+                      break;
-+
-+              case MULTIPART_EVENT_FILE_START:
-+            if(*tracking_key) {
-+                multipart_event_file_start *data = (multipart_event_file_start *) event_data;
-+
-+                bytes_processed = data->post_bytes_processed;
-+                strncpy(filename,*data->filename,127);
-+                temp_filename = NULL;
-+                strncpy(name,data->name,63);
-+                ALLOC_INIT_ZVAL(track);
-+                array_init(track);
-+                add_assoc_long(track, "total", content_length);
-+                add_assoc_long(track, "current", bytes_processed);
-+                add_assoc_string(track, "filename", filename, 1);
-+                add_assoc_string(track, "name", name, 1);
-+                add_assoc_long(track, "done", 0);
-+                add_assoc_double(track, "start_time", start_time);
-+                _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
-+                zval_ptr_dtor(&track);
-+            }
-+            break;
-+
-+              case MULTIPART_EVENT_FILE_DATA:
-+            if(*tracking_key) {
-+                multipart_event_file_data *data = (multipart_event_file_data *) event_data;
-+                bytes_processed = data->post_bytes_processed;
-+                ALLOC_INIT_ZVAL(track);
-+                array_init(track);
-+                add_assoc_long(track, "total", content_length);
-+                add_assoc_long(track, "current", bytes_processed);
-+                add_assoc_string(track, "filename", filename, 1);
-+                add_assoc_string(track, "name", name, 1);
-+                add_assoc_long(track, "done", 0);
-+                add_assoc_double(track, "start_time", start_time);
-+                if(bytes_processed - prev_bytes_processed > update_freq) {
-+                    _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
-+                    prev_bytes_processed = bytes_processed;
-+                }
-+                zval_ptr_dtor(&track);
-+                      }
-+                      break;
-+
-+              case MULTIPART_EVENT_FILE_END:
-+            if(*tracking_key) {
-+                multipart_event_file_end *data = (multipart_event_file_end *) event_data;
-+                bytes_processed = data->post_bytes_processed;
-+                cancel_upload = data->cancel_upload;
-+                temp_filename = data->temp_filename;
-+                ALLOC_INIT_ZVAL(track);
-+                array_init(track);
-+                add_assoc_long(track, "total", content_length);
-+                add_assoc_long(track, "current", bytes_processed);
-+                add_assoc_string(track, "filename", filename, 1);
-+                add_assoc_string(track, "name", name, 1);
-+                add_assoc_string(track, "temp_filename", temp_filename, 1);
-+                add_assoc_long(track, "cancel_upload", cancel_upload);
-+                add_assoc_long(track, "done", 0);
-+                add_assoc_double(track, "start_time", start_time);
-+                _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
-+                zval_ptr_dtor(&track);
-+                      }
-+                      break;
-+
-+              case MULTIPART_EVENT_END:
-+            if(*tracking_key) {
-+                double now = my_time(); 
-+                multipart_event_end *data = (multipart_event_end *) event_data;
-+                bytes_processed = data->post_bytes_processed;
-+                if(now>start_time) rate = 8.0*bytes_processed/(now-start_time);
-+                else rate = 8.0*bytes_processed;  /* Too quick */
-+                ALLOC_INIT_ZVAL(track);
-+                array_init(track);
-+                add_assoc_long(track, "total", content_length);
-+                add_assoc_long(track, "current", bytes_processed);
-+                add_assoc_double(track, "rate", rate);
-+                add_assoc_string(track, "filename", filename, 1);
-+                add_assoc_string(track, "name", name, 1);
-+                if(temp_filename) {
-+                    add_assoc_string(track, "temp_filename", temp_filename, 1);
-+                }
-+                add_assoc_long(track, "cancel_upload", cancel_upload);
-+                add_assoc_long(track, "done", 1);
-+                add_assoc_double(track, "start_time", start_time);
-+                _apc_store(tracking_key, key_length, track, 3600, 0 TSRMLS_CC);
-+                zval_ptr_dtor(&track);
-+                      }
-+                      break;
-+      }
-+}
-+
-+#endif
 +/*
 + * Local variables:
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_sem.c php-5.2.5/ext/apc/apc_sem.c
---- php-5.2.5-orig/ext/apc/apc_sem.c   1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_sem.c        2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,177 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc.php php-5.3.1/ext/apc/apc.php
+--- php-5.3.1.orig/ext/apc/apc.php     1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc.php  1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,1362 @@
++<?php
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -8713,1359 +8162,2034 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_sem.c php-5.2.5/ext/apc/apc_sem.c
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  | Authors: Ralf Becker <beckerr@php.net>                               |
++  |          Rasmus Lerdorf <rasmus@php.net>                             |
++  |          Ilia Alshanetsky <ilia@prohost.org>                         |
 +  +----------------------------------------------------------------------+
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
-+
 +   All other licensing and usage conditions are those of the PHP Group.
 +
 + */
 +
-+/* $Id: apc_sem.c,v 3.16 2006/03/12 00:31:45 rasmus Exp $ */
++$VERSION='$Id: apc.php 271315 2008-12-16 07:15:07Z shire $';
 +
-+#include "apc_sem.h"
-+#include "apc.h"
-+#include "php.h"
-+#include <sys/types.h>
-+#include <sys/ipc.h>
-+#include <sys/sem.h>
-+#include <sys/stat.h>
-+#include <unistd.h>
++////////// READ OPTIONAL CONFIGURATION FILE ////////////
++if (file_exists("apc.conf.php")) include("apc.conf.php");
++////////////////////////////////////////////////////////
 +
-+#if HAVE_SEMUN
-+/* we have semun, no need to define */
-+#else
-+#undef HAVE_SEMUN
-+union semun {
-+    int val;                  /* value for SETVAL */
-+    struct semid_ds *buf;     /* buffer for IPC_STAT, IPC_SET */
-+    unsigned short *array;    /* array for GETALL, SETALL */
-+                              /* Linux specific part: */
-+    struct seminfo *__buf;    /* buffer for IPC_INFO */
-+};
-+#define HAVE_SEMUN 1
-+#endif
++////////// BEGIN OF DEFAULT CONFIG AREA ///////////////////////////////////////////////////////////
 +
-+#ifndef SEM_R
-+# define SEM_R 0444
-+#endif
-+#ifndef SEM_A
-+# define SEM_A 0222
-+#endif
++defaults('USE_AUTHENTICATION',1);                     // Use (internal) authentication - best choice if 
++                                                                                      // no other authentication is available
++                                                                                      // If set to 0:
++                                                                                      //  There will be no further authentication. You 
++                                                                                      //  will have to handle this by yourself!
++                                                                                      // If set to 1:
++                                                                                      //  You need to change ADMIN_PASSWORD to make
++                                                                                      //  this work!
++defaults('ADMIN_USERNAME','apc');                     // Admin Username
++defaults('ADMIN_PASSWORD','password');        // Admin Password - CHANGE THIS TO ENABLE!!!
 +
-+/* always use SEM_UNDO, otherwise we risk deadlock */
-+#define USE_SEM_UNDO
++// (beckerr) I'm using a clear text password here, because I've no good idea how to let 
++//           users generate a md5 or crypt password in a easy way to fill it in above
 +
-+#ifdef USE_SEM_UNDO
-+# define UNDO SEM_UNDO
-+#else
-+# define UNDO 0
-+#endif
++//defaults('DATE_FORMAT', "d.m.Y H:i:s");     // German
++defaults('DATE_FORMAT', 'Y/m/d H:i:s');       // US
 +
-+int apc_sem_create(const char* pathname, int proj, int initval)
-+{
-+    int semid;
-+    int perms;
-+    union semun arg;
-+    key_t key;
++defaults('GRAPH_SIZE',200);                                   // Image size
 +
-+    perms = 0777;
++//defaults('PROXY', 'tcp://127.0.0.1:8080');
 +
-+    key = IPC_PRIVATE;
-+    if (pathname != NULL) {
-+        if ((key = ftok(pathname, proj)) < 0) {
-+            apc_eprint("apc_sem_create: ftok(%s,%d) failed:", pathname, proj);
-+        }
-+    }
-+    
-+    if ((semid = semget(key, 1, IPC_CREAT | IPC_EXCL | perms)) >= 0) {
-+        /* sempahore created for the first time, initialize now */
-+        arg.val = initval;
-+        if (semctl(semid, 0, SETVAL, arg) < 0) {
-+            apc_eprint("apc_sem_create: semctl(%d,...) failed:", semid);
-+        }
-+    }
-+    else if (errno == EEXIST) {
-+        /* sempahore already exists, don't initialize */
-+        if ((semid = semget(key, 1, perms)) < 0) {
-+            apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
-+        }
-+        /* insert <sleazy way to avoid race condition> here */
-+    }
-+    else {
-+        apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
-+    }
++////////// END OF DEFAULT CONFIG AREA /////////////////////////////////////////////////////////////
 +
-+    return semid;
-+}
 +
-+void apc_sem_destroy(int semid)
-+{
-+    /* we expect this call to fail often, so we do not check */
-+    union semun arg;
-+    semctl(semid, 0, IPC_RMID, arg);
++// "define if not defined"
++function defaults($d,$v) {
++      if (!defined($d)) define($d,$v); // or just @define(...)
 +}
 +
-+void apc_sem_lock(int semid)
-+{
-+    struct sembuf op;
-+
-+    op.sem_num = 0;
-+    op.sem_op  = -1;
-+    op.sem_flg = UNDO;
-+
-+    if (semop(semid, &op, 1) < 0) {
-+        if (errno != EINTR) {
-+            apc_eprint("apc_sem_lock: semop(%d) failed:", semid);
-+        }
-+    }
++// rewrite $PHP_SELF to block XSS attacks
++//
++$PHP_SELF= isset($_SERVER['PHP_SELF']) ? htmlentities(strip_tags($_SERVER['PHP_SELF'],''), ENT_QUOTES, 'UTF-8') : '';
++$time = time();
++$host = php_uname('n');
++if($host) { $host = '('.$host.')'; }
++if ($_SERVER['SERVER_ADDR']) {
++  $host .= ' ('.$_SERVER['SERVER_ADDR'].')';
 +}
 +
-+void apc_sem_unlock(int semid)
-+{
-+    struct sembuf op;
-+
-+    op.sem_num = 0;
-+    op.sem_op  = 1;
-+    op.sem_flg = UNDO;
++// operation constants
++define('OB_HOST_STATS',1);
++define('OB_SYS_CACHE',2);
++define('OB_USER_CACHE',3);
++define('OB_SYS_CACHE_DIR',4);
++define('OB_VERSION_CHECK',9);
 +
-+    if (semop(semid, &op, 1) < 0) {
-+        if (errno != EINTR) {
-+            apc_eprint("apc_sem_unlock: semop(%d) failed:", semid);
-+        }
-+    }
-+}
++// check validity of input variables
++$vardom=array(
++      'OB'    => '/^\d+$/',                   // operational mode switch
++      'CC'    => '/^[01]$/',                  // clear cache requested
++      'DU'    => '/^.*$/',                    // Delete User Key
++      'SH'    => '/^[a-z0-9]+$/',             // shared object description
 +
-+void apc_sem_wait_for_zero(int semid)
-+{
-+    struct sembuf op;
++      'IMG'   => '/^[123]$/',                 // image to generate
++      'LO'    => '/^1$/',                             // login requested
 +
-+    op.sem_num = 0;
-+    op.sem_op  = 0;
-+    op.sem_flg = UNDO;
++      'COUNT' => '/^\d+$/',                   // number of line displayed in list
++      'SCOPE' => '/^[AD]$/',                  // list view scope
++      'SORT1' => '/^[AHSMCDTZ]$/',    // first sort key
++      'SORT2' => '/^[DA]$/',                  // second sort key
++      'AGGR'  => '/^\d+$/',                   // aggregation by dir level
++      'SEARCH'        => '~^[a-zA-Z0-1/_.-]*$~'                       // aggregation by dir level
++);
 +
-+    if (semop(semid, &op, 1) < 0) {
-+        if (errno != EINTR) {
-+            apc_eprint("apc_sem_waitforzero: semop(%d) failed:", semid);
-+        }
-+    }
-+}
++// default cache mode
++$cache_mode='opcode';
 +
-+int apc_sem_get_value(int semid)
-+{
-+    union semun arg;
-+    unsigned short val[1];
++// cache scope
++$scope_list=array(
++      'A' => 'cache_list',
++      'D' => 'deleted_list'
++);
 +
-+    arg.array = val;
-+    if (semctl(semid, 0, GETALL, arg) < 0) {
-+        apc_eprint("apc_sem_getvalue: semctl(%d,...) failed:", semid);
-+    }
-+    return val[0];
++// handle POST and GET requests
++if (empty($_REQUEST)) {
++      if (!empty($_GET) && !empty($_POST)) {
++              $_REQUEST = array_merge($_GET, $_POST);
++      } else if (!empty($_GET)) {
++              $_REQUEST = $_GET;
++      } else if (!empty($_POST)) {
++              $_REQUEST = $_POST;
++      } else {
++              $_REQUEST = array();
++      }
 +}
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_sem.h php-5.2.5/ext/apc/apc_sem.h
---- php-5.2.5-orig/ext/apc/apc_sem.h   1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_sem.h        2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,51 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  +----------------------------------------------------------------------+
-+
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
-+
-+   All other licensing and usage conditions are those of the PHP Group.
-+
-+ */
-+
-+/* $Id: apc_sem.h,v 3.6 2006/03/12 00:31:45 rasmus Exp $ */
-+
-+#ifndef APC_SEM_H
-+#define APC_SEM_H
-+
-+/* Wrapper functions for SysV sempahores */
-+
-+extern int apc_sem_create(const char* pathname, int proj, int initval);
-+extern void apc_sem_destroy(int semid);
-+extern void apc_sem_lock(int semid);
-+extern void apc_sem_unlock(int semid);
-+extern void apc_sem_wait_for_zero(int semid);
-+extern int apc_sem_get_value(int semid);
-+
-+#endif
-+
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_shm.c php-5.2.5/ext/apc/apc_shm.c
---- php-5.2.5-orig/ext/apc/apc_shm.c   1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_shm.c        2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,110 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  +----------------------------------------------------------------------+
-+
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
-+
-+   All other licensing and usage conditions are those of the PHP Group.
-+
-+ */
-+
-+/* $Id: apc_shm.c,v 3.11 2007/05/09 22:15:33 shire Exp $ */
++// check parameter syntax
++foreach($vardom as $var => $dom) {
++      if (!isset($_REQUEST[$var])) {
++              $MYREQUEST[$var]=NULL;
++      } else if (!is_array($_REQUEST[$var]) && preg_match($dom.'D',$_REQUEST[$var])) {
++              $MYREQUEST[$var]=$_REQUEST[$var];
++      } else {
++              $MYREQUEST[$var]=$_REQUEST[$var]=NULL;
++      }
++}
 +
-+#include "apc_shm.h"
-+#include "apc.h"
-+#ifdef PHP_WIN32
-+/* shm functions are available in TSRM */
-+#include <tsrm/tsrm_win32.h>
-+#define key_t long
-+#else
-+#include <sys/ipc.h>
-+#include <sys/shm.h>
-+#include <sys/stat.h>
-+#endif
++// check parameter sematics
++if (empty($MYREQUEST['SCOPE'])) $MYREQUEST['SCOPE']="A";
++if (empty($MYREQUEST['SORT1'])) $MYREQUEST['SORT1']="H";
++if (empty($MYREQUEST['SORT2'])) $MYREQUEST['SORT2']="D";
++if (empty($MYREQUEST['OB']))  $MYREQUEST['OB']=OB_HOST_STATS;
++if (!isset($MYREQUEST['COUNT'])) $MYREQUEST['COUNT']=20;
++if (!isset($scope_list[$MYREQUEST['SCOPE']])) $MYREQUEST['SCOPE']='A';
 +
-+#ifndef SHM_R
-+# define SHM_R 0444 /* read permission */
-+#endif
-+#ifndef SHM_A
-+# define SHM_A 0222 /* write permission */
-+#endif
++$MY_SELF=
++      "$PHP_SELF".
++      "?SCOPE=".$MYREQUEST['SCOPE'].
++      "&SORT1=".$MYREQUEST['SORT1'].
++      "&SORT2=".$MYREQUEST['SORT2'].
++      "&COUNT=".$MYREQUEST['COUNT'];
++$MY_SELF_WO_SORT=
++      "$PHP_SELF".
++      "?SCOPE=".$MYREQUEST['SCOPE'].
++      "&COUNT=".$MYREQUEST['COUNT'];
 +
-+int apc_shm_create(const char* pathname, int proj, size_t size)
-+{
-+    int shmid;  /* shared memory id */
-+    int oflag;  /* permissions on shm */
-+    key_t key;  /* shm key returned by ftok */
++// authentication needed?
++//
++if (!USE_AUTHENTICATION) {
++      $AUTHENTICATED=1;
++} else {
++      $AUTHENTICATED=0;
++      if (ADMIN_PASSWORD!='password' && ($MYREQUEST['LO'] == 1 || isset($_SERVER['PHP_AUTH_USER']))) {
 +
-+    key = IPC_PRIVATE;
-+#ifndef PHP_WIN32
-+      /* no ftok yet for win32 */
-+    if (pathname != NULL) {
-+        if ((key = ftok(pathname, proj)) < 0) {
-+            apc_eprint("apc_shm_create: ftok failed:");
-+        }
-+    }
-+#endif
++              if (!isset($_SERVER['PHP_AUTH_USER']) ||
++                      !isset($_SERVER['PHP_AUTH_PW']) ||
++                      $_SERVER['PHP_AUTH_USER'] != ADMIN_USERNAME ||
++                      $_SERVER['PHP_AUTH_PW'] != ADMIN_PASSWORD) {
++                      Header("WWW-Authenticate: Basic realm=\"APC Login\"");
++                      Header("HTTP/1.0 401 Unauthorized");
 +
-+    oflag = IPC_CREAT | SHM_R | SHM_A;
-+    if ((shmid = shmget(key, size, oflag)) < 0) {
-+        apc_eprint("apc_shm_create: shmget(%d, %d, %d) failed: %s. It is possible that the chosen SHM segment size is higher than the operation system allows. Linux has usually a default limit of 32MB per segment.", key, size, oflag, strerror(errno));
-+    }
++                      echo <<<EOB
++                              <html><body>
++                              <h1>Rejected!</h1>
++                              <big>Wrong Username or Password!</big><br/>&nbsp;<br/>&nbsp;
++                              <big><a href='$PHP_SELF?OB={$MYREQUEST['OB']}'>Continue...</a></big>
++                              </body></html>
++EOB;
++                      exit;
++                      
++              } else {
++                      $AUTHENTICATED=1;
++              }
++      }
++}
++      
++// select cache mode
++if ($AUTHENTICATED && $MYREQUEST['OB'] == OB_USER_CACHE) {
++      $cache_mode='user';
++}
++// clear cache
++if ($AUTHENTICATED && isset($MYREQUEST['CC']) && $MYREQUEST['CC']) {
++      apc_clear_cache($cache_mode);
++}
 +
-+    return shmid;
++if ($AUTHENTICATED && !empty($MYREQUEST['DU'])) {
++      apc_delete($MYREQUEST['DU']);
 +}
 +
-+void apc_shm_destroy(int shmid)
-+{
-+    /* we expect this call to fail often, so we do not check */
-+    shmctl(shmid, IPC_RMID, 0);
++if(!function_exists('apc_cache_info') || !($cache=@apc_cache_info($cache_mode))) {
++      echo "No cache info available.  APC does not appear to be running.";
++  exit;
 +}
 +
-+void* apc_shm_attach(int shmid)
-+{
-+    void* shmaddr;  /* the shared memory address */
++$cache_user = apc_cache_info('user', 1);  
++$mem=apc_sma_info();
++if(!$cache['num_hits']) { $cache['num_hits']=1; $time++; }  // Avoid division by 0 errors on a cache clear
 +
-+    if ((int)(shmaddr = shmat(shmid, 0, 0)) == -1) {
-+        apc_eprint("apc_shm_attach: shmat failed:");
-+    }
++// don't cache this page
++//
++header("Cache-Control: no-store, no-cache, must-revalidate");  // HTTP/1.1
++header("Cache-Control: post-check=0, pre-check=0", false);
++header("Pragma: no-cache");                                    // HTTP/1.0
 +
-+    /*
-+     * We set the shmid for removal immediately after attaching to it. The
-+     * segment won't disappear until all processes have detached from it.
-+     */
-+    apc_shm_destroy(shmid);
-+    return shmaddr;
++function duration($ts) {
++    global $time;
++    $years = (int)((($time - $ts)/(7*86400))/52.177457);
++    $rem = (int)(($time-$ts)-($years * 52.177457 * 7 * 86400));
++    $weeks = (int)(($rem)/(7*86400));
++    $days = (int)(($rem)/86400) - $weeks*7;
++    $hours = (int)(($rem)/3600) - $days*24 - $weeks*7*24;
++    $mins = (int)(($rem)/60) - $hours*60 - $days*24*60 - $weeks*7*24*60;
++    $str = '';
++    if($years==1) $str .= "$years year, ";
++    if($years>1) $str .= "$years years, ";
++    if($weeks==1) $str .= "$weeks week, ";
++    if($weeks>1) $str .= "$weeks weeks, ";
++    if($days==1) $str .= "$days day,";
++    if($days>1) $str .= "$days days,";
++    if($hours == 1) $str .= " $hours hour and";
++    if($hours>1) $str .= " $hours hours and";
++    if($mins == 1) $str .= " 1 minute";
++    else $str .= " $mins minutes";
++    return $str;
 +}
 +
-+void apc_shm_detach(void* shmaddr)
-+{
-+    if (shmdt(shmaddr) < 0) {
-+        apc_eprint("apc_shm_detach: shmdt failed:");
-+    }
++// create graphics
++//
++function graphics_avail() {
++      return extension_loaded('gd');
 +}
++if (isset($MYREQUEST['IMG']))
++{
++      if (!graphics_avail()) {
++              exit(0);
++      }
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_shm.h php-5.2.5/ext/apc/apc_shm.h
---- php-5.2.5-orig/ext/apc/apc_shm.h   1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_shm.h        2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,54 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  +----------------------------------------------------------------------+
++      function fill_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$color2,$text='',$placeindex=0) {
++              $r=$diameter/2;
++              $w=deg2rad((360+$start+($end-$start)/2)%360);
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++              
++              if (function_exists("imagefilledarc")) {
++                      // exists only if GD 2.0.1 is avaliable
++                      imagefilledarc($im, $centerX+1, $centerY+1, $diameter, $diameter, $start, $end, $color1, IMG_ARC_PIE);
++                      imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2, IMG_ARC_PIE);
++                      imagefilledarc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color1, IMG_ARC_NOFILL|IMG_ARC_EDGED);
++              } else {
++                      imagearc($im, $centerX, $centerY, $diameter, $diameter, $start, $end, $color2);
++                      imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
++                      imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($start+1)) * $r, $centerY + sin(deg2rad($start)) * $r, $color2);
++                      imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end-1))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
++                      imageline($im, $centerX, $centerY, $centerX + cos(deg2rad($end))   * $r, $centerY + sin(deg2rad($end))   * $r, $color2);
++                      imagefill($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2, $color2);
++              }
++              if ($text) {
++                      if ($placeindex>0) {
++                              imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
++                              imagestring($im,4,$diameter, $placeindex*12,$text,$color1);     
++                              
++                      } else {
++                              imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
++                      }
++              }
++      } 
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++      function text_arc($im, $centerX, $centerY, $diameter, $start, $end, $color1,$text,$placeindex=0) {
++              $r=$diameter/2;
++              $w=deg2rad((360+$start+($end-$start)/2)%360);
 +
-+ */
++              if ($placeindex>0) {
++                      imageline($im,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$diameter, $placeindex*12,$color1);
++                      imagestring($im,4,$diameter, $placeindex*12,$text,$color1);     
++                              
++              } else {
++                      imagestring($im,4,$centerX + $r*cos($w)/2, $centerY + $r*sin($w)/2,$text,$color1);
++              }
++      } 
++      
++      function fill_box($im, $x, $y, $w, $h, $color1, $color2,$text='',$placeindex='') {
++              global $col_black;
++              $x1=$x+$w-1;
++              $y1=$y+$h-1;
 +
-+/* $Id: apc_shm.h,v 3.8 2007/05/23 01:23:21 auroraeosrose Exp $ */
++              imagerectangle($im, $x, $y1, $x1+1, $y+1, $col_black);
++              if($y1>$y) imagefilledrectangle($im, $x, $y, $x1, $y1, $color2);
++              else imagefilledrectangle($im, $x, $y1, $x1, $y, $color2);
++              imagerectangle($im, $x, $y1, $x1, $y, $color1);
++              if ($text) {
++                      if ($placeindex>0) {
++                      
++                              if ($placeindex<16)
++                              {
++                                      $px=5;
++                                      $py=$placeindex*12+6;
++                                      imagefilledrectangle($im, $px+90, $py+3, $px+90-4, $py-3, $color2);
++                                      imageline($im,$x,$y+$h/2,$px+90,$py,$color2);
++                                      imagestring($im,2,$px,$py-6,$text,$color1);     
++                                      
++                              } else {
++                                      if ($placeindex<31) {
++                                              $px=$x+40*2;
++                                              $py=($placeindex-15)*12+6;
++                                      } else {
++                                              $px=$x+40*2+100*intval(($placeindex-15)/15);
++                                              $py=($placeindex%15)*12+6;
++                                      }
++                                      imagefilledrectangle($im, $px, $py+3, $px-4, $py-3, $color2);
++                                      imageline($im,$x+$w,$y+$h/2,$px,$py,$color2);
++                                      imagestring($im,2,$px+2,$py-6,$text,$color1);   
++                              }
++                      } else {
++                              imagestring($im,4,$x+5,$y1-16,$text,$color1);
++                      }
++              }
++      }
 +
-+#ifndef APC_SHM_H
-+#define APC_SHM_H
 +
-+#include <sys/types.h>
-+#ifdef PHP_WIN32
-+#include <time.h>
-+#endif
++      $size = GRAPH_SIZE; // image size
++      if ($MYREQUEST['IMG']==3)
++              $image = imagecreate(2*$size+150, $size+10);
++      else
++              $image = imagecreate($size+50, $size+10);
 +
-+/* Wrapper functions for unix shared memory */
++      $col_white = imagecolorallocate($image, 0xFF, 0xFF, 0xFF);
++      $col_red   = imagecolorallocate($image, 0xD0, 0x60,  0x30);
++      $col_green = imagecolorallocate($image, 0x60, 0xF0, 0x60);
++      $col_black = imagecolorallocate($image,   0,   0,   0);
++      imagecolortransparent($image,$col_white);
 +
-+extern int apc_shm_create(const char* name, int proj, size_t size);
-+extern void apc_shm_destroy(int shmid);
-+extern void* apc_shm_attach(int shmid);
-+extern void apc_shm_detach(void* shmaddr);
++      switch ($MYREQUEST['IMG']) {
++      
++      case 1:
++              $s=$mem['num_seg']*$mem['seg_size'];
++              $a=$mem['avail_mem'];
++              $x=$y=$size/2;
++              $fuzz = 0.000001;
 +
-+#endif
++              // This block of code creates the pie chart.  It is a lot more complex than you
++              // would expect because we try to visualize any memory fragmentation as well.
++              $angle_from = 0;
++              $string_placement=array();
++              for($i=0; $i<$mem['num_seg']; $i++) {   
++                      $ptr = 0;
++                      $free = $mem['block_lists'][$i];
++                      uasort($free, 'block_sort');
++                      foreach($free as $block) {
++                              if($block['offset']!=$ptr) {       // Used block
++                                      $angle_to = $angle_from+($block['offset']-$ptr)/$s;
++                                      if(($angle_to+$fuzz)>1) $angle_to = 1;
++                                      if( ($angle_to*360) - ($angle_from*360) >= 1) {
++                                              fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
++                                              if (($angle_to-$angle_from)>0.05) {
++                                                      array_push($string_placement, array($angle_from,$angle_to));
++                                              }
++                                      }
++                                      $angle_from = $angle_to;
++                              }
++                              $angle_to = $angle_from+($block['size'])/$s;
++                              if(($angle_to+$fuzz)>1) $angle_to = 1;
++                              if( ($angle_to*360) - ($angle_from*360) >= 1) {
++                                      fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_green);
++                                      if (($angle_to-$angle_from)>0.05) {
++                                              array_push($string_placement, array($angle_from,$angle_to));
++                                      }
++                              }
++                              $angle_from = $angle_to;
++                              $ptr = $block['offset']+$block['size'];
++                      }
++                      if ($ptr < $mem['seg_size']) { // memory at the end 
++                              $angle_to = $angle_from + ($mem['seg_size'] - $ptr)/$s;
++                              if(($angle_to+$fuzz)>1) $angle_to = 1;
++                              fill_arc($image,$x,$y,$size,$angle_from*360,$angle_to*360,$col_black,$col_red);
++                              if (($angle_to-$angle_from)>0.05) {
++                                      array_push($string_placement, array($angle_from,$angle_to));
++                              }
++                      }
++              }
++              foreach ($string_placement as $angle) {
++                      text_arc($image,$x,$y,$size,$angle[0]*360,$angle[1]*360,$col_black,bsize($s*($angle[1]-$angle[0])));
++              }
++              break;
++              
++      case 2: 
++              $s=$cache['num_hits']+$cache['num_misses'];
++              $a=$cache['num_hits'];
++              
++              fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
++              fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
++              break;
++              
++      case 3:
++              $s=$mem['num_seg']*$mem['seg_size'];
++              $a=$mem['avail_mem'];
++              $x=130;
++              $y=1;
++              $j=1;
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_signal.c php-5.2.5/ext/apc/apc_signal.c
---- php-5.2.5-orig/ext/apc/apc_signal.c        1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_signal.c     2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,178 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Lucas Nealan <lucas@php.net>                                |
-+  +----------------------------------------------------------------------+
++              // This block of code creates the bar chart.  It is a lot more complex than you
++              // would expect because we try to visualize any memory fragmentation as well.
++              for($i=0; $i<$mem['num_seg']; $i++) {   
++                      $ptr = 0;
++                      $free = $mem['block_lists'][$i];
++                      uasort($free, 'block_sort');
++                      foreach($free as $block) {
++                              if($block['offset']!=$ptr) {       // Used block
++                                      $h=(GRAPH_SIZE-5)*($block['offset']-$ptr)/$s;
++                                      if ($h>0) {
++                                                $j++;
++                                              if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($block['offset']-$ptr),$j);
++                                                else fill_box($image,$x,$y,50,$h,$col_black,$col_red);
++                                        }
++                                      $y+=$h;
++                              }
++                              $h=(GRAPH_SIZE-5)*($block['size'])/$s;
++                              if ($h>0) {
++                                        $j++;
++                                      if($j<75) fill_box($image,$x,$y,50,$h,$col_black,$col_green,bsize($block['size']),$j);
++                                      else fill_box($image,$x,$y,50,$h,$col_black,$col_green);
++                                }
++                              $y+=$h;
++                              $ptr = $block['offset']+$block['size'];
++                      }
++                      if ($ptr < $mem['seg_size']) { // memory at the end 
++                              $h = (GRAPH_SIZE-5) * ($mem['seg_size'] - $ptr) / $s;
++                              if ($h > 0) {
++                                      fill_box($image,$x,$y,50,$h,$col_black,$col_red,bsize($mem['seg_size']-$ptr),$j++);
++                              }
++                      }
++              }
++              break;
++      case 4: 
++              $s=$cache['num_hits']+$cache['num_misses'];
++              $a=$cache['num_hits'];
++                      
++              fill_box($image, 30,$size,50,-$a*($size-21)/$s,$col_black,$col_green,sprintf("%.1f%%",$cache['num_hits']*100/$s));
++              fill_box($image,130,$size,50,-max(4,($s-$a)*($size-21)/$s),$col_black,$col_red,sprintf("%.1f%%",$cache['num_misses']*100/$s));
++              break;
++      
++      }
++      header("Content-type: image/png");
++      imagepng($image);
++      exit;
++}
 +
-+   This software was contributed to PHP by Facebook Inc. in 2007.
-+   
-+   Future revisions and derivatives of this source code must acknowledge
-+   Facebook Inc. as the original contributor of this module by leaving
-+   this note intact in the source code.
++// pretty printer for byte values
++//
++function bsize($s) {
++      foreach (array('','K','M','G') as $i => $k) {
++              if ($s < 1024) break;
++              $s/=1024;
++      }
++      return sprintf("%5.1f %sBytes",$s,$k);
++}
 +
-+   All other licensing and usage conditions are those of the PHP Group.
-+ */
++// sortable table header in "scripts for this host" view
++function sortheader($key,$name,$extra='') {
++      global $MYREQUEST, $MY_SELF_WO_SORT;
++      
++      if ($MYREQUEST['SORT1']==$key) {
++              $MYREQUEST['SORT2'] = $MYREQUEST['SORT2']=='A' ? 'D' : 'A';
++      }
++      return "<a class=sortable href=\"$MY_SELF_WO_SORT$extra&SORT1=$key&SORT2=".$MYREQUEST['SORT2']."\">$name</a>";
 +
-+ /* $Id: apc_signal.c,v 1.2 2007/12/26 22:38:43 rasmus Exp $ */
++}
 +
-+ /* Allows apc to install signal handlers and maintain signalling
-+    to already registered handlers. Registers all signals that
-+    coredump by default and unmaps the shared memory segment
-+    before the coredump. Note: PHP module init is called before 
-+    signals are set by Apache and thus apc_set_signals should
-+    be called in request init (RINIT)
-+  */
++// create menu entry 
++function menu_entry($ob,$title) {
++      global $MYREQUEST,$MY_SELF;
++      if ($MYREQUEST['OB']!=$ob) {
++              return "<li><a href=\"$MY_SELF&OB=$ob\">$title</a></li>";
++      } else if (empty($MYREQUEST['SH'])) {
++              return "<li><span class=active>$title</span></li>";
++      } else {
++              return "<li><a class=\"child_active\" href=\"$MY_SELF&OB=$ob\">$title</a></li>";        
++      }
++}
 +
-+#include <signal.h>
-+#include "apc_globals.h"
-+#include "apc_sma.h"
-+#include "apc_signal.h"
++function put_login_link($s="Login")
++{
++      global $MY_SELF,$MYREQUEST,$AUTHENTICATED;
++      // needs ADMIN_PASSWORD to be changed!
++      //
++      if (!USE_AUTHENTICATION) {
++              return;
++      } else if (ADMIN_PASSWORD=='password')
++      {
++              print <<<EOB
++                      <a href="#" onClick="javascript:alert('You need to set a password at the top of apc.php before this will work!');return false";>$s</a>
++EOB;
++      } else if ($AUTHENTICATED) {
++              print <<<EOB
++                      '{$_SERVER['PHP_AUTH_USER']}'&nbsp;logged&nbsp;in!
++EOB;
++      } else{
++              print <<<EOB
++                      <a href="$MY_SELF&LO=1&OB={$MYREQUEST['OB']}">$s</a>
++EOB;
++      }
++}
 +
-+static apc_signal_info_t apc_signal_info = {0};
++function block_sort($array1, $array2)
++{
++      if ($array1['offset'] > $array2['offset']) {
++              return 1;
++      } else {
++              return -1;
++      }
++}
 +
-+static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*));
-+static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context);
-+static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context);
 +
-+/* {{{ apc_core_unmap 
-+ *  Coredump signal handler, unmaps shm and calls previously installed handlers 
-+ */
-+static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context) 
-+{
-+    apc_sma_cleanup();
-+    apc_rehandle_signal(signo, siginfo, context);
++?>
++<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
++<html>
++<head><title>APC INFO <?php echo $host ?></title>
++<style><!--
++body { background:white; font-size:100.01%; margin:0; padding:0; }
++body,p,td,th,input,submit { font-size:0.8em;font-family:arial,helvetica,sans-serif; }
++* html body   {font-size:0.8em}
++* html p      {font-size:0.8em}
++* html td     {font-size:0.8em}
++* html th     {font-size:0.8em}
++* html input  {font-size:0.8em}
++* html submit {font-size:0.8em}
++td { vertical-align:top }
++a { color:black; font-weight:none; text-decoration:none; }
++a:hover { text-decoration:underline; }
++div.content { padding:1em 1em 1em 1em; position:absolute; width:97%; z-index:100; }
 +
-+#if !defined(WIN32) && !defined(NETWARE)
-+    kill(getpid(), signo);
-+#else
-+    raise(signo);
-+#endif
-+} /* }}} */
 +
-+/* {{{ apc_rehandle_signal
-+ *  Call the previously registered handler for a signal
-+ */
-+static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context)
-+{
-+    int i;
-+    apc_signal_entry_t p_sig = {0};
++div.head div.login {
++      position:absolute;
++      right: 1em;
++      top: 1.2em;
++      color:white;
++      width:6em;
++      }
++div.head div.login a {
++      position:absolute;
++      right: 0em;
++      background:rgb(119,123,180);
++      border:solid rgb(102,102,153) 2px;
++      color:white;
++      font-weight:bold;
++      padding:0.1em 0.5em 0.1em 0.5em;
++      text-decoration:none;
++      }
++div.head div.login a:hover {
++      background:rgb(193,193,244);
++      }
 +
-+    for (i=0;  (i < apc_signal_info.installed && p_sig.signo != signo);  i++) {
-+        p_sig = *apc_signal_info.prev[i];
-+        if (p_sig.signo == signo) {
-+            if (p_sig.siginfo) {
-+                (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context);
-+            } else {
-+                (*(void (*)(int))p_sig.handler)(signo);
-+            }
-+        }
-+    }
++h1.apc { background:rgb(153,153,204); margin:0; padding:0.5em 1em 0.5em 1em; }
++* html h1.apc { margin-bottom:-7px; }
++h1.apc a:hover { text-decoration:none; color:rgb(90,90,90); }
++h1.apc div.logo span.logo {
++      background:rgb(119,123,180);
++      color:black;
++      border-right: solid black 1px;
++      border-bottom: solid black 1px;
++      font-style:italic;
++      font-size:1em;
++      padding-left:1.2em;
++      padding-right:1.2em;
++      text-align:right;
++      }
++h1.apc div.logo span.name { color:white; font-size:0.7em; padding:0 0.8em 0 2em; }
++h1.apc div.nameinfo { color:white; display:inline; font-size:0.4em; margin-left: 3em; }
++h1.apc div.copy { color:black; font-size:0.4em; position:absolute; right:1em; }
++hr.apc {
++      background:white;
++      border-bottom:solid rgb(102,102,153) 1px;
++      border-style:none;
++      border-top:solid rgb(102,102,153) 10px;
++      height:12px;
++      margin:0;
++      margin-top:1px;
++      padding:0;
++}
 +
-+} /* }}} */
++ol,menu { margin:1em 0 0 0; padding:0.2em; margin-left:1em;}
++ol.menu li { display:inline; margin-right:0.7em; list-style:none; font-size:85%}
++ol.menu a {
++      background:rgb(153,153,204);
++      border:solid rgb(102,102,153) 2px;
++      color:white;
++      font-weight:bold;
++      margin-right:0em;
++      padding:0.1em 0.5em 0.1em 0.5em;
++      text-decoration:none;
++      margin-left: 5px;
++      }
++ol.menu a.child_active {
++      background:rgb(153,153,204);
++      border:solid rgb(102,102,153) 2px;
++      color:white;
++      font-weight:bold;
++      margin-right:0em;
++      padding:0.1em 0.5em 0.1em 0.5em;
++      text-decoration:none;
++      border-left: solid black 5px;
++      margin-left: 0px;
++      }
++ol.menu span.active {
++      background:rgb(153,153,204);
++      border:solid rgb(102,102,153) 2px;
++      color:black;
++      font-weight:bold;
++      margin-right:0em;
++      padding:0.1em 0.5em 0.1em 0.5em;
++      text-decoration:none;
++      border-left: solid black 5px;
++      }
++ol.menu span.inactive {
++      background:rgb(193,193,244);
++      border:solid rgb(182,182,233) 2px;
++      color:white;
++      font-weight:bold;
++      margin-right:0em;
++      padding:0.1em 0.5em 0.1em 0.5em;
++      text-decoration:none;
++      margin-left: 5px;
++      }
++ol.menu a:hover {
++      background:rgb(193,193,244);
++      text-decoration:none;
++      }
++      
++      
++div.info {
++      background:rgb(204,204,204);
++      border:solid rgb(204,204,204) 1px;
++      margin-bottom:1em;
++      }
++div.info h2 {
++      background:rgb(204,204,204);
++      color:black;
++      font-size:1em;
++      margin:0;
++      padding:0.1em 1em 0.1em 1em;
++      }
++div.info table {
++      border:solid rgb(204,204,204) 1px;
++      border-spacing:0;
++      width:100%;
++      }
++div.info table th {
++      background:rgb(204,204,204);
++      color:white;
++      margin:0;
++      padding:0.1em 1em 0.1em 1em;
++      }
++div.info table th a.sortable { color:black; }
++div.info table tr.tr-0 { background:rgb(238,238,238); }
++div.info table tr.tr-1 { background:rgb(221,221,221); }
++div.info table td { padding:0.3em 1em 0.3em 1em; }
++div.info table td.td-0 { border-right:solid rgb(102,102,153) 1px; white-space:nowrap; }
++div.info table td.td-n { border-right:solid rgb(102,102,153) 1px; }
++div.info table td h3 {
++      color:black;
++      font-size:1.1em;
++      margin-left:-0.3em;
++      }
 +
-+/* {{{ apc_register_signal
-+ *  Set a handler for a previously installed signal and save so we can 
-+ *  callback when handled 
-+ */
-+static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*))
-+{
-+#if HAVE_SIGACTION
-+    struct sigaction sa = {0};
-+    apc_signal_entry_t p_sig = {0};
++div.graph { margin-bottom:1em }
++div.graph h2 { background:rgb(204,204,204);; color:black; font-size:1em; margin:0; padding:0.1em 1em 0.1em 1em; }
++div.graph table { border:solid rgb(204,204,204) 1px; color:black; font-weight:normal; width:100%; }
++div.graph table td.td-0 { background:rgb(238,238,238); }
++div.graph table td.td-1 { background:rgb(221,221,221); }
++div.graph table td { padding:0.2em 1em 0.4em 1em; }
 +
-+    if (sigaction(signo, NULL, &sa) == 0) {
-+        if ((void*)sa.sa_handler == (void*)handler) {
-+            return SUCCESS;
-+        }
++div.div1,div.div2 { margin-bottom:1em; width:35em; }
++div.div3 { position:absolute; left:40em; top:1em; width:580px; }
++//div.div3 { position:absolute; left:37em; top:1em; right:1em; }
 +
-+        if (sa.sa_handler != SIG_ERR && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) {
-+            p_sig.signo = signo;
-+            p_sig.siginfo = ((sa.sa_flags & SA_SIGINFO) == SA_SIGINFO);
-+            p_sig.handler = (void *)sa.sa_handler;
-+           
-+            apc_signal_info.prev = (apc_signal_entry_t **)apc_erealloc(apc_signal_info.prev, (apc_signal_info.installed+1)*sizeof(apc_signal_entry_t *));
-+            apc_signal_info.prev[apc_signal_info.installed] = (apc_signal_entry_t *)apc_emalloc(sizeof(apc_signal_entry_t));
-+            *apc_signal_info.prev[apc_signal_info.installed++] = p_sig;
-+        } else {
-+            /* inherit flags and mask if already set */
-+            sigemptyset(&sa.sa_mask);
-+            sa.sa_flags = 0;
-+            sa.sa_flags |= SA_SIGINFO; /* we'll use a siginfo handler */
-+#if defined(SA_ONESHOT)
-+            sa.sa_flags = SA_ONESHOT;
-+#elif defined(SA_RESETHAND)
-+            sa.sa_flags = SA_RESETHAND;
-+#endif
-+        }
-+        sa.sa_handler = (void*)handler;
++div.sorting { margin:1.5em 0em 1.5em 2em }
++.center { text-align:center }
++.aright { position:absolute;right:1em }
++.right { text-align:right }
++.ok { color:rgb(0,200,0); font-weight:bold}
++.failed { color:rgb(200,0,0); font-weight:bold}
 +
-+        if (sigaction(signo, &sa, NULL) < 0) {
-+            apc_wprint("Error installing apc signal handler for %d", signo);
-+        }
++span.box {
++      border: black solid 1px;
++      border-right:solid black 2px;
++      border-bottom:solid black 2px;
++      padding:0 0.5em 0 0.5em;
++      margin-right:1em;
++}
++span.green { background:#60F060; padding:0 0.5em 0 0.5em}
++span.red { background:#D06030; padding:0 0.5em 0 0.5em }
 +
-+        return SUCCESS;
-+    }
-+#endif
-+    return FAILURE;
-+} /* }}} */
++div.authneeded {
++      background:rgb(238,238,238);
++      border:solid rgb(204,204,204) 1px;
++      color:rgb(200,0,0);
++      font-size:1.2em;
++      font-weight:bold;
++      padding:2em;
++      text-align:center;
++      }
++      
++input {
++      background:rgb(153,153,204);
++      border:solid rgb(102,102,153) 2px;
++      color:white;
++      font-weight:bold;
++      margin-right:1em;
++      padding:0.1em 0.5em 0.1em 0.5em;
++      }
++//-->
++</style>
++</head>
++<body>
++<div class="head">
++      <h1 class="apc">
++              <div class="logo"><span class="logo"><a href="http://pecl.php.net/package/APC">APC</a></span></div>
++              <div class="nameinfo">Opcode Cache</div>
++      </h1>
++      <div class="login">
++      <?php put_login_link(); ?>
++      </div>
++      <hr class="apc">
++</div>
++<?php
 +
-+/* {{{ apc_set_signals
-+ *  Install our signal handlers */
-+void apc_set_signals(TSRMLS_D) 
-+{
-+    if (APCG(coredump_unmap) && apc_signal_info.installed == 0) {
-+        /* ISO C standard signals that coredump */
-+        apc_register_signal(SIGSEGV, apc_core_unmap);
-+        apc_register_signal(SIGABRT, apc_core_unmap);
-+        apc_register_signal(SIGFPE, apc_core_unmap);
-+        apc_register_signal(SIGILL, apc_core_unmap);
-+        /* extended signals that coredump */
-+#ifdef SIGBUS
-+        apc_register_signal(SIGBUS, apc_core_unmap);
-+#endif
-+#ifdef SIGABORT
-+        apc_register_signal(SIGABORT, apc_core_unmap);
-+#endif
-+#ifdef SIGEMT
-+        apc_register_signal(SIGEMT, apc_core_unmap);
-+#endif
-+#ifdef SIGIOT
-+        apc_register_signal(SIGIOT, apc_core_unmap);
-+#endif
-+#ifdef SIGQUIT
-+        apc_register_signal(SIGQUIT, apc_core_unmap);
-+#endif
-+#ifdef SIGSYS
-+        apc_register_signal(SIGSYS, apc_core_unmap);
-+#endif
-+#ifdef SIGTRAP
-+        apc_register_signal(SIGTRAP, apc_core_unmap);
-+#endif
-+#ifdef SIGXCPU
-+        apc_register_signal(SIGXCPU, apc_core_unmap);
-+#endif
-+#ifdef SIGXFSZ
-+        apc_register_signal(SIGXFSZ, apc_core_unmap);
-+#endif
-+    }
-+} /* }}} */
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_signal.h php-5.2.5/ext/apc/apc_signal.h
---- php-5.2.5-orig/ext/apc/apc_signal.h        1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_signal.h     2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,50 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Lucas Nealan <lucas@php.net>                                |
-+  +----------------------------------------------------------------------+
++// Display main Menu
++echo <<<EOB
++      <ol class=menu>
++      <li><a href="$MY_SELF&OB={$MYREQUEST['OB']}&SH={$MYREQUEST['SH']}">Refresh Data</a></li>
++EOB;
++echo
++      menu_entry(1,'View Host Stats'),
++      menu_entry(2,'System Cache Entries');
++if ($AUTHENTICATED) {
++      echo menu_entry(4,'Per-Directory Entries');
++}
++echo
++      menu_entry(3,'User Cache Entries'),
++      menu_entry(9,'Version Check');
++      
++if ($AUTHENTICATED) {
++      echo <<<EOB
++              <li><a class="aright" href="$MY_SELF&CC=1&OB={$MYREQUEST['OB']}" onClick="javascipt:return confirm('Are you sure?');">Clear $cache_mode Cache</a></li>
++EOB;
++}
++echo <<<EOB
++      </ol>
++EOB;
 +
-+ */
 +
-+/* $Id: apc_signal.h,v 1.1 2007/12/26 22:36:06 rasmus Exp $ */
++// CONTENT
++echo <<<EOB
++      <div class=content>
++EOB;
 +
-+#ifndef APC_SIGNAL_H
-+#define APC_SIGNAL_H
++// MAIN SWITCH STATEMENT 
 +
-+#include "apc.h"
-+#include "apc_php.h"
++switch ($MYREQUEST['OB']) {
 +
-+typedef struct apc_signal_entry_t {
-+    int signo;          /* signal number */
-+    int siginfo;        /* siginfo style handler calling */
-+    void* handler;      /* signal handler */
-+} apc_signal_entry_t;
 +
-+typedef struct apc_signal_info_t {
-+    int installed;                  /* How many signals we've installed handles for */
-+    apc_signal_entry_t **prev;      /* Previous signal handlers */
-+} apc_signal_info_t;
 +
-+void apc_set_signals(TSRMLS_D);
 +
-+#endif
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_sma.c php-5.2.5/ext/apc/apc_sma.c
---- php-5.2.5-orig/ext/apc/apc_sma.c   1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_sma.c        2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,628 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  +----------------------------------------------------------------------+
++// -----------------------------------------------
++// Host Stats
++// -----------------------------------------------
++case OB_HOST_STATS:
++      $mem_size = $mem['num_seg']*$mem['seg_size'];
++      $mem_avail= $mem['avail_mem'];
++      $mem_used = $mem_size-$mem_avail;
++      $seg_size = bsize($mem['seg_size']);
++      $req_rate = sprintf("%.2f",($cache['num_hits']+$cache['num_misses'])/($time-$cache['start_time']));
++      $hit_rate = sprintf("%.2f",($cache['num_hits'])/($time-$cache['start_time']));
++      $miss_rate = sprintf("%.2f",($cache['num_misses'])/($time-$cache['start_time']));
++      $insert_rate = sprintf("%.2f",($cache['num_inserts'])/($time-$cache['start_time']));
++      $req_rate_user = sprintf("%.2f",($cache_user['num_hits']+$cache_user['num_misses'])/($time-$cache_user['start_time']));
++      $hit_rate_user = sprintf("%.2f",($cache_user['num_hits'])/($time-$cache_user['start_time']));
++      $miss_rate_user = sprintf("%.2f",($cache_user['num_misses'])/($time-$cache_user['start_time']));
++      $insert_rate_user = sprintf("%.2f",($cache_user['num_inserts'])/($time-$cache_user['start_time']));
++      $apcversion = phpversion('apc');
++      $phpversion = phpversion();
++      $number_files = $cache['num_entries']; 
++    $size_files = bsize($cache['mem_size']);
++      $number_vars = $cache_user['num_entries'];
++    $size_vars = bsize($cache_user['mem_size']);
++      $i=0;
++      echo <<< EOB
++              <div class="info div1"><h2>General Cache Information</h2>
++              <table cellspacing=0><tbody>
++              <tr class=tr-0><td class=td-0>APC Version</td><td>$apcversion</td></tr>
++              <tr class=tr-1><td class=td-0>PHP Version</td><td>$phpversion</td></tr>
++EOB;
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++      if(!empty($_SERVER['SERVER_NAME']))
++              echo "<tr class=tr-0><td class=td-0>APC Host</td><td>{$_SERVER['SERVER_NAME']} $host</td></tr>\n";
++      if(!empty($_SERVER['SERVER_SOFTWARE']))
++              echo "<tr class=tr-1><td class=td-0>Server Software</td><td>{$_SERVER['SERVER_SOFTWARE']}</td></tr>\n";
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++      echo <<<EOB
++              <tr class=tr-0><td class=td-0>Shared Memory</td><td>{$mem['num_seg']} Segment(s) with $seg_size 
++    <br/> ({$cache['memory_type']} memory, {$cache['locking_type']} locking)
++    </td></tr>
++EOB;
++      echo   '<tr class=tr-1><td class=td-0>Start Time</td><td>',date(DATE_FORMAT,$cache['start_time']),'</td></tr>';
++      echo   '<tr class=tr-0><td class=td-0>Uptime</td><td>',duration($cache['start_time']),'</td></tr>';
++      echo   '<tr class=tr-1><td class=td-0>File Upload Support</td><td>',$cache['file_upload_progress'],'</td></tr>';
++      echo <<<EOB
++              </tbody></table>
++              </div>
 +
-+ */
-+
-+/* $Id: apc_sma.c,v 1.69 2007/12/26 21:35:39 gopalv Exp $ */
-+
-+#include "apc_sma.h"
-+#include "apc.h"
-+#include "apc_globals.h"
-+#include "apc_lock.h"
-+#include "apc_shm.h"
-+#include <limits.h>
-+#if APC_MMAP
-+void *apc_mmap(char *file_mask, size_t size);
-+void apc_unmap(void* shmaddr, size_t size);
-+#endif
-+
-+/* {{{ locking macros */
-+#define LOCK(c)         { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_lock(c); }
-+#define RDLOCK(c)       { HANDLE_BLOCK_INTERRUPTIONS(); apc_lck_rdlock(c); }
-+#define UNLOCK(c)       { apc_lck_unlock(c); HANDLE_UNBLOCK_INTERRUPTIONS(); }
-+/* }}} */
++              <div class="info div1"><h2>File Cache Information</h2>
++              <table cellspacing=0><tbody>
++              <tr class=tr-0><td class=td-0>Cached Files</td><td>$number_files ($size_files)</td></tr>
++              <tr class=tr-1><td class=td-0>Hits</td><td>{$cache['num_hits']}</td></tr>
++              <tr class=tr-0><td class=td-0>Misses</td><td>{$cache['num_misses']}</td></tr>
++              <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate cache requests/second</td></tr>
++              <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate cache requests/second</td></tr>
++              <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate cache requests/second</td></tr>
++              <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate cache requests/second</td></tr>
++              <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache['expunges']}</td></tr>
++              </tbody></table>
++              </div>
 +
-+enum { DEFAULT_NUMSEG=1, DEFAULT_SEGSIZE=30*1024*1024 };
++              <div class="info div1"><h2>User Cache Information</h2>
++              <table cellspacing=0><tbody>
++    <tr class=tr-0><td class=td-0>Cached Variables</td><td>$number_vars ($size_vars)</td></tr>
++              <tr class=tr-1><td class=td-0>Hits</td><td>{$cache_user['num_hits']}</td></tr>
++              <tr class=tr-0><td class=td-0>Misses</td><td>{$cache_user['num_misses']}</td></tr>
++              <tr class=tr-1><td class=td-0>Request Rate (hits, misses)</td><td>$req_rate_user cache requests/second</td></tr>
++              <tr class=tr-0><td class=td-0>Hit Rate</td><td>$hit_rate_user cache requests/second</td></tr>
++              <tr class=tr-1><td class=td-0>Miss Rate</td><td>$miss_rate_user cache requests/second</td></tr>
++              <tr class=tr-0><td class=td-0>Insert Rate</td><td>$insert_rate_user cache requests/second</td></tr>
++              <tr class=tr-1><td class=td-0>Cache full count</td><td>{$cache_user['expunges']}</td></tr>
 +
-+static int sma_initialized = 0;     /* true if the sma has been initialized */
-+static unsigned int sma_numseg;     /* number of shm segments to allow */
-+static size_t sma_segsize;          /* size of each shm segment */
-+static size_t* sma_segments;        /* array of shm segment ids */
-+static void** sma_shmaddrs;         /* array of shm segment addresses */
-+static int sma_lastseg = 0;         /* index of MRU segment */
++              </tbody></table>
++              </div>
 +
-+typedef struct header_t header_t;
-+struct header_t {
-+    apc_lck_t sma_lock;     /* segment lock, MUST BE ALIGNED for futex locks */
-+    size_t segsize;         /* size of entire segment */
-+    size_t avail;           /* bytes available (not necessarily contiguous) */
-+    size_t nfoffset;        /* start next fit search from this offset       */
-+#if ALLOC_DISTRIBUTION
-+    size_t adist[30];
-+#endif
-+};
++              <div class="info div2"><h2>Runtime Settings</h2><table cellspacing=0><tbody>
++EOB;
 +
++      $j = 0;
++      foreach (ini_get_all('apc') as $k => $v) {
++              echo "<tr class=tr-$j><td class=td-0>",$k,"</td><td>",str_replace(',',',<br />',$v['local_value']),"</td></tr>\n";
++              $j = 1 - $j;
++      }
 +
-+/* do not enable for threaded http servers */
-+/* #define __APC_SMA_DEBUG__ 1 */
++      if($mem['num_seg']>1 || $mem['num_seg']==1 && count($mem['block_lists'][0])>1)
++              $mem_note = "Memory Usage<br /><font size=-2>(multiple slices indicate fragments)</font>";
++      else
++              $mem_note = "Memory Usage";
 +
-+#ifdef __APC_SMA_DEBUG__
-+/* global counter for identifying blocks 
-+ * Technically it is possible to do the same
-+ * using offsets, but double allocations of the
-+ * same offset can happen. */
-+static volatile size_t block_id = 0;
-+#endif
++      echo <<< EOB
++              </tbody></table>
++              </div>
 +
-+#define APC_SMA_CANARIES 1   
++              <div class="graph div3"><h2>Host Status Diagrams</h2>
++              <table cellspacing=0><tbody>
++EOB;
++      $size='width='.(GRAPH_SIZE+50).' height='.(GRAPH_SIZE+10);
++      echo <<<EOB
++              <tr>
++              <td class=td-0>$mem_note</td>
++              <td class=td-1>Hits &amp; Misses</td>
++              </tr>
++EOB;
 +
-+typedef struct block_t block_t;
-+struct block_t {
-+    size_t size;       /* size of this block */
-+    size_t next;       /* offset in segment of next free block */
-+#ifdef APC_SMA_CANARIES
-+    size_t canary;     /* canary to check for memory overwrites */
-+#endif
-+#ifdef __APC_SMA_DEBUG__
-+    size_t id;         /* identifier for the memory block */ 
-+#endif
-+};
++      echo
++              graphics_avail() ? 
++                        '<tr>'.
++                        "<td class=td-0><img alt=\"\" $size src=\"$PHP_SELF?IMG=1&$time\"></td>".
++                        "<td class=td-1><img alt=\"\" $size src=\"$PHP_SELF?IMG=2&$time\"></td></tr>\n"
++                      : "",
++              '<tr>',
++              '<td class=td-0><span class="green box">&nbsp;</span>Free: ',bsize($mem_avail).sprintf(" (%.1f%%)",$mem_avail*100/$mem_size),"</td>\n",
++              '<td class=td-1><span class="green box">&nbsp;</span>Hits: ',$cache['num_hits'].sprintf(" (%.1f%%)",$cache['num_hits']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n",
++              '</tr>',
++              '<tr>',
++              '<td class=td-0><span class="red box">&nbsp;</span>Used: ',bsize($mem_used ).sprintf(" (%.1f%%)",$mem_used *100/$mem_size),"</td>\n",
++              '<td class=td-1><span class="red box">&nbsp;</span>Misses: ',$cache['num_misses'].sprintf(" (%.1f%%)",$cache['num_misses']*100/($cache['num_hits']+$cache['num_misses'])),"</td>\n";
++      echo <<< EOB
++              </tr>
++              </tbody></table>
 +
-+/* The macros BLOCKAT and OFFSET are used for convenience throughout this
-+ * module. Both assume the presence of a variable shmaddr that points to the
-+ * beginning of the shared memory segment in question. */
++              <br/>
++              <h2>Detailed Memory Usage and Fragmentation</h2>
++              <table cellspacing=0><tbody>
++              <tr>
++              <td class=td-0 colspan=2><br/>
++EOB;
 +
-+#define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
-+#define OFFSET(block) ((size_t)(((char*)block) - (char*)shmaddr))
++      // Fragementation: (freeseg - 1) / total_seg
++      $nseg = $freeseg = $fragsize = $freetotal = 0;
++      for($i=0; $i<$mem['num_seg']; $i++) {
++              $ptr = 0;
++              foreach($mem['block_lists'][$i] as $block) {
++                      if ($block['offset'] != $ptr) {
++                              ++$nseg;
++                      }
++                      $ptr = $block['offset'] + $block['size'];
++                        /* Only consider blocks <5M for the fragmentation % */
++                        if($block['size']<(5*1024*1024)) $fragsize+=$block['size'];
++                        $freetotal+=$block['size'];
++              }
++              $freeseg += count($mem['block_lists'][$i]);
++      }
++      
++      if ($freeseg > 1) {
++              $frag = sprintf("%.2f%% (%s out of %s in %d fragments)", ($fragsize/$freetotal)*100,bsize($fragsize),bsize($freetotal),$freeseg);
++      } else {
++              $frag = "0%";
++      }
 +
-+/* Canary macros for setting, checking and resetting memory canaries */
-+#ifdef APC_SMA_CANARIES
-+    #define SET_CANARY(v) (v)->canary = 0x42424242
-+    #define CHECK_CANARY(v) assert((v)->canary == 0x42424242)
-+    #define RESET_CANARY(v) (v)->canary = -42
-+#else
-+    #define SET_CANARY(v) 
-+    #define CHECK_CANARY(v)
-+    #define RESET_CANARY(v)
-+#endif
++      if (graphics_avail()) {
++              $size='width='.(2*GRAPH_SIZE+150).' height='.(GRAPH_SIZE+10);
++              echo <<<EOB
++                      <img alt="" $size src="$PHP_SELF?IMG=3&$time">
++EOB;
++      }
++      echo <<<EOB
++              </br>Fragmentation: $frag
++              </td>
++              </tr>
++EOB;
++        if(isset($mem['adist'])) {
++          foreach($mem['adist'] as $i=>$v) {
++            $cur = pow(2,$i); $nxt = pow(2,$i+1)-1;
++            if($i==0) $range = "1";
++            else $range = "$cur - $nxt";
++            echo "<tr><th align=right>$range</th><td align=right>$v</td></tr>\n";
++          }
++        }
++        echo <<<EOB
++              </tbody></table>
++              </div>
++EOB;
++              
++      break;
 +
 +
-+#ifdef max
-+#undef max
-+#endif
-+#define max(a, b) ((a) > (b) ? (a) : (b))
++// -----------------------------------------------
++// User Cache Entries
++// -----------------------------------------------
++case OB_USER_CACHE:
++      if (!$AUTHENTICATED) {
++    echo '<div class="error">You need to login to see the user values here!<br/>&nbsp;<br/>';
++              put_login_link("Login now!");
++              echo '</div>';
++              break;
++      }
++      $fieldname='info';
++      $fieldheading='User Entry Label';
++      $fieldkey='info';
 +
-+/* {{{ ALIGNWORD: pad up x, aligned to the system's word boundary */
-+typedef union { void* p; int i; long l; double d; void (*f)(); } apc_word_t;
-+#define ALIGNWORD(x) (sizeof(apc_word_t) * (1 + (((x)-1)/sizeof(apc_word_t))))
-+#define MINBLOCKSIZE (ALIGNWORD(1) + ALIGNWORD(sizeof(block_t)))
-+/* }}} */
++// -----------------------------------------------
++// System Cache Entries               
++// -----------------------------------------------
++case OB_SYS_CACHE:    
++      if (!isset($fieldname))
++      {
++              $fieldname='filename';
++              $fieldheading='Script Filename';
++              if(ini_get("apc.stat")) $fieldkey='inode';
++              else $fieldkey='filename'; 
++      }
++      if (!empty($MYREQUEST['SH']))
++      {
++              echo <<< EOB
++                      <div class="info"><table cellspacing=0><tbody>
++                      <tr><th>Attribute</th><th>Value</th></tr>
++EOB;
 +
-+/* {{{ sma_allocate: tries to allocate size bytes in a segment */
-+static int sma_allocate(void* shmaddr, size_t size)
-+{
-+    header_t* header;       /* header of shared memory segment */
-+    block_t* prv;           /* block prior to working block */
-+    block_t* cur;           /* working block in list */
-+    block_t* prvnextfit;    /* block before next fit */
-+    size_t realsize;        /* actual size of block needed, including header */
-+    size_t last_offset;     /* save the last search offset */
-+    int wrapped=0;
-+    const size_t block_size = ALIGNWORD(sizeof(struct block_t));
++              $m=0;
++              foreach($scope_list as $j => $list) {
++                      foreach($cache[$list] as $i => $entry) {
++                              if (md5($entry[$fieldkey])!=$MYREQUEST['SH']) continue;
++                              foreach($entry as $k => $value) {
++                                      if (!$AUTHENTICATED) {
++                                              // hide all path entries if not logged in
++                                              $value=preg_replace('/^.*(\\/|\\\\)/','<i>&lt;hidden&gt;</i>/',$value);
++                                      }
 +
-+    realsize = ALIGNWORD(size + block_size);
++                                      if ($k == "num_hits") {
++                                              $value=sprintf("%s (%.2f%%)",$value,$value*100/$cache['num_hits']);
++                                      }
++                                      if ($k == 'deletion_time') {
++                                              if(!$entry['deletion_time']) $value = "None";
++                                      }
++                                      echo
++                                              "<tr class=tr-$m>",
++                                              "<td class=td-0>",ucwords(preg_replace("/_/"," ",$k)),"</td>",
++                                              "<td class=td-last>",(preg_match("/time/",$k) && $value!='None') ? date(DATE_FORMAT,$value) : $value,"</td>",
++                                              "</tr>";
++                                      $m=1-$m;
++                              }
++                              if($fieldkey=='info') {
++                                      echo "<tr class=tr-$m><td class=td-0>Stored Value</td><td class=td-last><pre>";
++                                      $output = var_export(apc_fetch($entry[$fieldkey]),true);
++                                      echo htmlspecialchars($output);
++                                      echo "</pre></td></tr>\n";
++                              }
++                              break;
++                      }
++              }
 +
-+    /*
-+     * First, insure that the segment contains at least realsize free bytes,
-+     * even if they are not contiguous.
-+     */
-+    header = (header_t*) shmaddr;
-+    if (header->avail < realsize) {
-+        return -1;
-+    }
++              echo <<<EOB
++                      </tbody></table>
++                      </div>
++EOB;
++              break;
++      }
 +
-+    prvnextfit = 0;     /* initially null (no fit) */
-+    last_offset = 0;
-+
-+    /* If we have a next fit offset, start searching from there */
-+    if(header->nfoffset) {
-+        prv = BLOCKAT(header->nfoffset);
-+        /* if prv is the last block, jump to the beginning */
-+        if(prv->next == 0) {
-+            prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
-+            wrapped = 1;
-+        }
-+    } else {    
-+        prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
-+    }
-+   
-+    CHECK_CANARY(prv);
-+
-+    while (prv->next != header->nfoffset) {
-+        cur = BLOCKAT(prv->next);
-+#ifdef __APC_SMA_DEBUG__
-+        CHECK_CANARY(cur);
-+#endif
-+        /* If it can fit realiszie bytes in cur block, stop searching */
-+        if (cur->size >= realsize) {
-+            prvnextfit = prv;
-+            break;
-+        }
-+        last_offset = prv->next;
-+        prv = cur;
-+        if(wrapped && (prv->next >= header->nfoffset)) break;
++      $cols=6;
++      echo <<<EOB
++              <div class=sorting><form>Scope:
++              <input type=hidden name=OB value={$MYREQUEST['OB']}>
++              <select name=SCOPE>
++EOB;
++      echo 
++              "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
++              "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
++              "</select>",
++              ", Sorting:<select name=SORT1>",
++              "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Hits</option>",
++              "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Size</option>",
++              "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">$fieldheading</option>",
++              "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Last accessed</option>",
++              "<option value=M",$MYREQUEST['SORT1']=='M' ? " selected":"",">Last modified</option>",
++              "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Created at</option>",
++              "<option value=D",$MYREQUEST['SORT1']=='D' ? " selected":"",">Deleted at</option>";
++      if($fieldname=='info') echo
++              "<option value=D",$MYREQUEST['SORT1']=='T' ? " selected":"",">Timeout</option>";
++      echo 
++              '</select>',
++              '<select name=SORT2>',
++              '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
++              '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
++              '</select>',
++              '<select name=COUNT onChange="form.submit()">',
++              '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
++              '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
++              '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
++              '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
++              '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
++              '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
++              '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
++              '<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
++              '</select>',
++    '&nbsp; Search: <input name=SEARCH value="',$MYREQUEST['SEARCH'],'" type=text size=25/>',
++              '&nbsp;<input type=submit value="GO!">',
++              '</form></div>';
++
++  if (isset($MYREQUEST['SEARCH'])) {
++   // Don't use preg_quote because we want the user to be able to specify a
++   // regular expression subpattern.
++   $MYREQUEST['SEARCH'] = '/'.str_replace('/', '\\/', $MYREQUEST['SEARCH']).'/i';
++   if (preg_match($MYREQUEST['SEARCH'], 'test') === false) {
++     echo '<div class="error">Error: enter a valid regular expression as a search query.</div>';
++     break;
++   }
++  }
++
++  echo
++              '<div class="info"><table cellspacing=0><tbody>',
++              '<tr>',
++              '<th>',sortheader('S',$fieldheading,  "&OB=".$MYREQUEST['OB']),'</th>',
++              '<th>',sortheader('H','Hits',         "&OB=".$MYREQUEST['OB']),'</th>',
++              '<th>',sortheader('Z','Size',         "&OB=".$MYREQUEST['OB']),'</th>',
++              '<th>',sortheader('A','Last accessed',"&OB=".$MYREQUEST['OB']),'</th>',
++              '<th>',sortheader('M','Last modified',"&OB=".$MYREQUEST['OB']),'</th>',
++              '<th>',sortheader('C','Created at',   "&OB=".$MYREQUEST['OB']),'</th>';
 +
-+        /* Check to see if we need to wrap around and search from the top */
-+        if(header->nfoffset && prv->next == 0) {
-+            prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
-+#ifdef __APC_SMA_DEBUG__
-+            CHECK_CANARY(prv);
-+#endif
-+            last_offset = 0;
-+            wrapped = 1;
-+        } 
-+    }
++      if($fieldname=='info') {
++              $cols+=2;
++               echo '<th>',sortheader('T','Timeout',"&OB=".$MYREQUEST['OB']),'</th>';
++      }
++      echo '<th>',sortheader('D','Deleted at',"&OB=".$MYREQUEST['OB']),'</th></tr>';
 +
-+    if (prvnextfit == 0) {
-+        header->nfoffset = 0;
-+        return -1;
-+    }
++      // builds list with alpha numeric sortable keys
++      //
++      $list = array();
++      foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $i => $entry) {
++              switch($MYREQUEST['SORT1']) {
++                      case 'A': $k=sprintf('%015d-',$entry['access_time']);   break;
++                      case 'H': $k=sprintf('%015d-',$entry['num_hits']);              break;
++                      case 'Z': $k=sprintf('%015d-',$entry['mem_size']);              break;
++                      case 'M': $k=sprintf('%015d-',$entry['mtime']);                 break;
++                      case 'C': $k=sprintf('%015d-',$entry['creation_time']); break;
++                      case 'T': $k=sprintf('%015d-',$entry['ttl']);                   break;
++                      case 'D': $k=sprintf('%015d-',$entry['deletion_time']); break;
++                      case 'S': $k='';                                                                                break;
++              }
++              if (!$AUTHENTICATED) {
++                      // hide all path entries if not logged in
++                      $list[$k.$entry[$fieldname]]=preg_replace('/^.*(\\/|\\\\)/','*hidden*/',$entry);
++              } else {
++                      $list[$k.$entry[$fieldname]]=$entry;
++              }
++      }
 +
-+    prv = prvnextfit;
-+    cur = BLOCKAT(prv->next);
++      if ($list) {
++              
++              // sort list
++              //
++              switch ($MYREQUEST['SORT2']) {
++                      case "A":       krsort($list);  break;
++                      case "D":       ksort($list);   break;
++              }
++              
++              // output list
++              $i=0;
++              foreach($list as $k => $entry) {
++      if(!$MYREQUEST['SEARCH'] || preg_match($MYREQUEST['SEARCH'], $entry[$fieldname]) != 0) {  
++        $field_value = htmlentities(strip_tags($entry[$fieldname],''), ENT_QUOTES, 'UTF-8');
++        echo
++          '<tr class=tr-',$i%2,'>',
++          "<td class=td-0><a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&SH=",md5($entry[$fieldkey]),"\">",$field_value,'</a></td>',
++          '<td class="td-n center">',$entry['num_hits'],'</td>',
++          '<td class="td-n right">',$entry['mem_size'],'</td>',
++          '<td class="td-n center">',date(DATE_FORMAT,$entry['access_time']),'</td>',
++          '<td class="td-n center">',date(DATE_FORMAT,$entry['mtime']),'</td>',
++          '<td class="td-n center">',date(DATE_FORMAT,$entry['creation_time']),'</td>';
 +
-+    CHECK_CANARY(prv);
-+    CHECK_CANARY(cur);
++        if($fieldname=='info') {
++          if($entry['ttl'])
++            echo '<td class="td-n center">'.$entry['ttl'].' seconds</td>';
++          else
++            echo '<td class="td-n center">None</td>';
++        }
++        if ($entry['deletion_time']) {
 +
-+    if (cur->size == realsize || (cur->size > realsize && cur->size < (realsize + (MINBLOCKSIZE * 2)))) {
-+        /* cur is big enough for realsize, but too small to split - unlink it */
-+        prv->next = cur->next;
-+    }
-+    else {
-+        block_t* nxt;      /* the new block (chopped part of cur) */
-+        size_t nxtoffset;  /* offset of the block currently after cur */
-+        size_t oldsize;    /* size of cur before split */
++          echo '<td class="td-last center">', date(DATE_FORMAT,$entry['deletion_time']), '</td>';
++        } else if ($MYREQUEST['OB'] == OB_USER_CACHE) {
 +
-+        /* nextfit is too big; split it into two smaller blocks */
-+        nxtoffset = cur->next;
-+        oldsize = cur->size;
-+        prv->next += realsize;  /* skip over newly allocated block */
-+        cur->size = realsize;   /* Set the size of this new block */
-+        nxt = BLOCKAT(prv->next);
-+        nxt->next = nxtoffset;  /* Re-link the shortened block */
-+        nxt->size = oldsize - realsize;  /* and fix the size */
-+        SET_CANARY(nxt);
-+#ifdef __APC_SMA_DEBUG__
-+        nxt->id = -1;
-+#endif
-+    }
++          echo '<td class="td-last center">';
++          echo '[<a href="', $MY_SELF, '&OB=', $MYREQUEST['OB'], '&DU=', urlencode($entry[$fieldkey]), '">Delete Now</a>]';
++          echo '</td>';
++        } else {
++          echo '<td class="td-last center"> &nbsp; </td>';
++        }
++        echo '</tr>';
++        $i++;
++        if ($i == $MYREQUEST['COUNT'])
++          break;
++      }
++              }
++              
++      } else {
++              echo '<tr class=tr-0><td class="center" colspan=',$cols,'><i>No data</i></td></tr>';
++      }
++      echo <<< EOB
++              </tbody></table>
++EOB;
 +
-+    /* update the block header */
-+    header->avail -= cur->size;
-+#if ALLOC_DISTRIBUTION
-+    header->adist[(int)(log(size)/log(2))]++;
-+#endif
++      if ($list && $i < count($list)) {
++              echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
++      }
 +
-+    header->nfoffset = last_offset;
++      echo <<< EOB
++              </div>
++EOB;
++      break;
 +
-+    SET_CANARY(cur);
-+#ifdef __APC_SMA_DEBUG__
-+    cur->id = ++block_id;
-+    fprintf(stderr, "allocate(realsize=%d,size=%d,id=%d)\n", (int)(size), (int)(cur->size), cur->id);
-+#endif
 +
-+    return OFFSET(cur) + block_size;
-+}
-+/* }}} */
++// -----------------------------------------------
++// Per-Directory System Cache Entries
++// -----------------------------------------------
++case OB_SYS_CACHE_DIR:        
++      if (!$AUTHENTICATED) {
++              break;
++      }
 +
-+/* {{{ sma_deallocate: deallocates the block at the given offset */
-+static int sma_deallocate(void* shmaddr, int offset)
-+{
-+    header_t* header;   /* header of shared memory segment */
-+    block_t* cur;       /* the new block to insert */
-+    block_t* prv;       /* the block before cur */
-+    block_t* nxt;       /* the block after cur */
-+    size_t size;        /* size of deallocated block */
++      echo <<<EOB
++              <div class=sorting><form>Scope:
++              <input type=hidden name=OB value={$MYREQUEST['OB']}>
++              <select name=SCOPE>
++EOB;
++      echo 
++              "<option value=A",$MYREQUEST['SCOPE']=='A' ? " selected":"",">Active</option>",
++              "<option value=D",$MYREQUEST['SCOPE']=='D' ? " selected":"",">Deleted</option>",
++              "</select>",
++              ", Sorting:<select name=SORT1>",
++              "<option value=H",$MYREQUEST['SORT1']=='H' ? " selected":"",">Total Hits</option>",
++              "<option value=Z",$MYREQUEST['SORT1']=='Z' ? " selected":"",">Total Size</option>",
++              "<option value=T",$MYREQUEST['SORT1']=='T' ? " selected":"",">Number of Files</option>",
++              "<option value=S",$MYREQUEST['SORT1']=='S' ? " selected":"",">Directory Name</option>",
++              "<option value=A",$MYREQUEST['SORT1']=='A' ? " selected":"",">Avg. Size</option>",
++              "<option value=C",$MYREQUEST['SORT1']=='C' ? " selected":"",">Avg. Hits</option>",
++              '</select>',
++              '<select name=SORT2>',
++              '<option value=D',$MYREQUEST['SORT2']=='D' ? ' selected':'','>DESC</option>',
++              '<option value=A',$MYREQUEST['SORT2']=='A' ? ' selected':'','>ASC</option>',
++              '</select>',
++              '<select name=COUNT onChange="form.submit()">',
++              '<option value=10 ',$MYREQUEST['COUNT']=='10' ? ' selected':'','>Top 10</option>',
++              '<option value=20 ',$MYREQUEST['COUNT']=='20' ? ' selected':'','>Top 20</option>',
++              '<option value=50 ',$MYREQUEST['COUNT']=='50' ? ' selected':'','>Top 50</option>',
++              '<option value=100',$MYREQUEST['COUNT']=='100'? ' selected':'','>Top 100</option>',
++              '<option value=150',$MYREQUEST['COUNT']=='150'? ' selected':'','>Top 150</option>',
++              '<option value=200',$MYREQUEST['COUNT']=='200'? ' selected':'','>Top 200</option>',
++              '<option value=500',$MYREQUEST['COUNT']=='500'? ' selected':'','>Top 500</option>',
++              '<option value=0  ',$MYREQUEST['COUNT']=='0'  ? ' selected':'','>All</option>',
++              '</select>',
++              ", Group By Dir Level:<select name=AGGR>",
++              "<option value='' selected>None</option>";
++              for ($i = 1; $i < 10; $i++)
++                      echo "<option value=$i",$MYREQUEST['AGGR']==$i ? " selected":"",">$i</option>";
++              echo '</select>',
++              '&nbsp;<input type=submit value="GO!">',
++              '</form></div>',
 +
-+    offset -= ALIGNWORD(sizeof(struct block_t));
-+    assert(offset >= 0);
++              '<div class="info"><table cellspacing=0><tbody>',
++              '<tr>',
++              '<th>',sortheader('S','Directory Name', "&OB=".$MYREQUEST['OB']),'</th>',
++              '<th>',sortheader('T','Number of Files',"&OB=".$MYREQUEST['OB']),'</th>',
++              '<th>',sortheader('H','Total Hits',     "&OB=".$MYREQUEST['OB']),'</th>',
++              '<th>',sortheader('Z','Total Size',     "&OB=".$MYREQUEST['OB']),'</th>',
++              '<th>',sortheader('C','Avg. Hits',      "&OB=".$MYREQUEST['OB']),'</th>',
++              '<th>',sortheader('A','Avg. Size',      "&OB=".$MYREQUEST['OB']),'</th>',
++              '</tr>';
 +
-+    /* find position of new block in free list */
-+    cur = BLOCKAT(offset);
-+    prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
-+   
-+    CHECK_CANARY(cur);
++      // builds list with alpha numeric sortable keys
++      //
++      $tmp = $list = array();
++      foreach($cache[$scope_list[$MYREQUEST['SCOPE']]] as $entry) {
++              $n = dirname($entry['filename']);
++              if ($MYREQUEST['AGGR'] > 0) {
++                      $n = preg_replace("!^(/?(?:[^/\\\\]+[/\\\\]){".($MYREQUEST['AGGR']-1)."}[^/\\\\]*).*!", "$1", $n);
++              }
++              if (!isset($tmp[$n])) {
++                      $tmp[$n] = array('hits'=>0,'size'=>0,'ents'=>0);
++              }
++              $tmp[$n]['hits'] += $entry['num_hits'];
++              $tmp[$n]['size'] += $entry['mem_size'];
++              ++$tmp[$n]['ents'];
++      }
 +
-+#ifdef __APC_SMA_DEBUG__
-+    CHECK_CANARY(prv);
-+    fprintf(stderr, "free(%p, size=%d,id=%d)\n", cur, (int)(cur->size), cur->id);
-+#endif
-+    while (prv->next != 0 && prv->next < offset) {
-+        prv = BLOCKAT(prv->next);
-+#ifdef __APC_SMA_DEBUG__
-+        CHECK_CANARY(prv);
-+#endif
-+    }
-+    
-+    CHECK_CANARY(prv);
++      foreach ($tmp as $k => $v) {
++              switch($MYREQUEST['SORT1']) {
++                      case 'A': $kn=sprintf('%015d-',$v['size'] / $v['ents']);break;
++                      case 'T': $kn=sprintf('%015d-',$v['ents']);             break;
++                      case 'H': $kn=sprintf('%015d-',$v['hits']);             break;
++                      case 'Z': $kn=sprintf('%015d-',$v['size']);             break;
++                      case 'C': $kn=sprintf('%015d-',$v['hits'] / $v['ents']);break;
++                      case 'S': $kn = $k;                                     break;
++              }
++              $list[$kn.$k] = array($k, $v['ents'], $v['hits'], $v['size']);
++      }
 +
-+    /* insert new block after prv */
-+    cur->next = prv->next;
-+    prv->next = offset;
++      if ($list) {
++              
++              // sort list
++              //
++              switch ($MYREQUEST['SORT2']) {
++                      case "A":       krsort($list);  break;
++                      case "D":       ksort($list);   break;
++              }
++              
++              // output list
++              $i = 0;
++              foreach($list as $entry) {
++                      echo
++                              '<tr class=tr-',$i%2,'>',
++                              "<td class=td-0>",$entry[0],'</a></td>',
++                              '<td class="td-n center">',$entry[1],'</td>',
++                              '<td class="td-n center">',$entry[2],'</td>',
++                              '<td class="td-n center">',$entry[3],'</td>',
++                              '<td class="td-n center">',round($entry[2] / $entry[1]),'</td>',
++                              '<td class="td-n center">',round($entry[3] / $entry[1]),'</td>',
++                              '</tr>';
 +
-+#ifdef __APC_SMA_DEBUG__
-+    CHECK_CANARY(cur);
-+    cur->id = -1;
-+#endif
-+    
-+    /* update the block header */
-+    header = (header_t*) shmaddr;
-+    header->avail += cur->size;
-+    size = cur->size;
++                      if (++$i == $MYREQUEST['COUNT']) break;
++              }
++              
++      } else {
++              echo '<tr class=tr-0><td class="center" colspan=6><i>No data</i></td></tr>';
++      }
++      echo <<< EOB
++              </tbody></table>
++EOB;
 +
-+    if (((char *)prv) + prv->size == (char *) cur) {
-+        /* cur and prv share an edge, combine them */
-+        prv->size += cur->size;
-+        prv->next = cur->next;
-+        RESET_CANARY(cur);
-+        cur = prv;
-+    }
++      if ($list && $i < count($list)) {
++              echo "<a href=\"$MY_SELF&OB=",$MYREQUEST['OB'],"&COUNT=0\"><i>",count($list)-$i,' more available...</i></a>';
++      }
++
++      echo <<< EOB
++              </div>
++EOB;
++      break;
 +
-+    nxt = BLOCKAT(cur->next);
++// -----------------------------------------------
++// Version check
++// -----------------------------------------------
++case OB_VERSION_CHECK:
++      echo <<<EOB
++              <div class="info"><h2>APC Version Information</h2>
++              <table cellspacing=0><tbody>
++              <tr>
++              <th></th>
++              </tr>
++EOB;
++  if (defined('PROXY')) {
++    $ctxt = stream_context_create( array( 'http' => array( 'proxy' => PROXY, 'request_fulluri' => True ) ) );
++    $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss", False, $ctxt);
++  } else {
++    $rss = @file_get_contents("http://pecl.php.net/feeds/pkg_apc.rss");
++  }
++      if (!$rss) {
++              echo '<tr class="td-last center"><td>Unable to fetch version information.</td></tr>';
++      } else {
++              $apcversion = phpversion('apc');
 +
-+    if (((char *)cur) + cur->size == (char *) nxt) {
-+        /* cur and nxt shared an edge, combine them */
-+        cur->size += nxt->size;
-+        cur->next = nxt->next;
-+#ifdef __APC_SMA_DEBUG__
-+        CHECK_CANARY(nxt);
-+        nxt->id = -1; /* assert this or set it ? */
-+#endif
-+        RESET_CANARY(nxt);
-+    }
-+    header->nfoffset = 0;  /* Reset the next fit search marker */
++              preg_match('!<title>APC ([0-9.]+)</title>!', $rss, $match);
++              echo '<tr class="tr-0 center"><td>';
++              if (version_compare($apcversion, $match[1], '>=')) {
++                      echo '<div class="ok">You are running the latest version of APC ('.$apcversion.')</div>';
++                      $i = 3;
++              } else {
++                      echo '<div class="failed">You are running an older version of APC ('.$apcversion.'), 
++                              newer version '.$match[1].' is available at <a href="http://pecl.php.net/package/APC/'.$match[1].'">
++                              http://pecl.php.net/package/APC/'.$match[1].'</a>
++                              </div>';
++                      $i = -1;
++              }
++              echo '</td></tr>';
++              echo '<tr class="tr-0"><td><h3>Change Log:</h3><br/>';
++
++              preg_match_all('!<(title|description)>([^<]+)</\\1>!', $rss, $match);
++              next($match[2]); next($match[2]);
++
++              while (list(,$v) = each($match[2])) {
++                      list(,$ver) = explode(' ', $v, 2);
++                      if ($i < 0 && version_compare($apcversion, $ver, '>=')) {
++                              break;
++                      } else if (!$i--) {
++                              break;
++                      }
++                      echo "<b><a href=\"http://pecl.php.net/package/APC/$ver\">".htmlspecialchars($v)."</a></b><br><blockquote>";
++                      echo nl2br(htmlspecialchars(current($match[2])))."</blockquote>";
++                      next($match[2]);
++              }
++              echo '</td></tr>';
++      }
++      echo <<< EOB
++              </tbody></table>
++              </div>
++EOB;
++      break;
 +
-+    return size;
 +}
-+/* }}} */
 +
-+/* {{{ apc_sma_init */
++echo <<< EOB
++      </div>
++EOB;
 +
-+void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask)
-+{
-+    int i;
++?>
 +
-+    if (sma_initialized) {
-+        return;
-+    }
-+    sma_initialized = 1;
++<!-- <?php echo "\nBased on APCGUI By R.Becker\n$VERSION\n"?> -->
++</body>
++</html>
+diff -Naur php-5.3.1.orig/ext/apc/apc_php.h php-5.3.1/ext/apc/apc_php.h
+--- php-5.3.1.orig/ext/apc/apc_php.h   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_php.h        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,74 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          George Schlossnagle <george@omniti.com>                     |
++  |          Rasmus Lerdorf <rasmus@php.net>                             |
++  |          Arun C. Murthy <arunc@yahoo-inc.com>                        |
++  |          Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
++  +----------------------------------------------------------------------+
 +
-+#if APC_MMAP
-+    /*
-+     * I don't think multiple anonymous mmaps makes any sense
-+     * so force sma_numseg to 1 in this case
-+     */
-+    if(!mmap_file_mask || 
-+       (mmap_file_mask && !strlen(mmap_file_mask)) ||
-+       (mmap_file_mask && !strcmp(mmap_file_mask, "/dev/zero"))) {
-+        sma_numseg = 1;
-+    } else {
-+        sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
-+    }
-+#else
-+    sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
-+#endif
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
 +
-+    sma_segsize = segsize > 0 ? segsize : DEFAULT_SEGSIZE;
++   All other licensing and usage conditions are those of the PHP Group.
 +
-+    sma_segments = (size_t*) apc_emalloc(sma_numseg*sizeof(size_t));
-+    sma_shmaddrs = (void**) apc_emalloc(sma_numseg*sizeof(void*));
-+    
-+    for (i = 0; i < sma_numseg; i++) {
-+        header_t*   header;
-+        block_t*    block;
-+        void*       shmaddr;
++ */
 +
-+#if APC_MMAP
-+        sma_segments[i] = sma_segsize;
-+        sma_shmaddrs[i] = apc_mmap(mmap_file_mask, sma_segsize);
-+        if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6);
-+#else
-+        sma_segments[i] = apc_shm_create(NULL, i, sma_segsize);
-+        sma_shmaddrs[i] = apc_shm_attach(sma_segments[i]);
-+#endif
-+        shmaddr = sma_shmaddrs[i];
-+    
-+        header = (header_t*) shmaddr;
-+        apc_lck_create(NULL, 0, 1, header->sma_lock);
-+        header->segsize = sma_segsize;
-+        header->avail = sma_segsize - ALIGNWORD(sizeof(header_t)) - ALIGNWORD(sizeof(block_t));
-+        header->nfoffset = 0;
-+#if ALLOC_DISTRIBUTION
-+              {
-+           int j;
-+           for(j=0; j<30; j++) header->adist[j] = 0; 
-+        }
-+#endif 
-+        block = BLOCKAT(ALIGNWORD(sizeof(header_t)));
-+        block->size = 0;
-+        block->next = ALIGNWORD(sizeof(header_t)) + ALIGNWORD(sizeof(block_t));
-+        SET_CANARY(block);
-+#ifdef __APC_SMA_DEBUG__
-+        block->id = -1;
-+#endif
-+        block = BLOCKAT(block->next);
-+        block->size = header->avail;
-+        block->next = 0;
-+        SET_CANARY(block);
-+#ifdef __APC_SMA_DEBUG__
-+        block->id = -1;
-+#endif
-+    }
-+}
-+/* }}} */
++/* $Id: apc_php.h 268255 2008-11-04 05:42:11Z rasmus $ */
 +
-+/* {{{ apc_sma_cleanup */
-+void apc_sma_cleanup()
-+{
-+    int i;
++#ifndef APC_PHP_H
++#define APC_PHP_H
 +
-+    assert(sma_initialized);
++/*
++ * The purpose of this header file is to include all PHP and Zend headers that
++ * are typically needed elsewhere in APC. This makes it easy to insure that
++ * all required headers are available.
++ */
 +
-+    for (i = 0; i < sma_numseg; i++) {
-+        apc_lck_destroy(((header_t*)sma_shmaddrs[i])->sma_lock);
-+#if APC_MMAP
-+        apc_unmap(sma_shmaddrs[i], sma_segments[i]);
-+#else
-+        apc_shm_detach(sma_shmaddrs[i]);
++#include "php.h"
++#include "zend.h"
++#include "zend_API.h"
++#include "zend_compile.h"
++#include "zend_hash.h"
++#include "zend_extensions.h"
++
++#if ZEND_MODULE_API_NO > 20060613
++#define ZEND_ENGINE_2_3
++#endif
++#if ZEND_MODULE_API_NO > 20050922
++#define ZEND_ENGINE_2_2
++#endif
++#if ZEND_MODULE_API_NO > 20050921
++#define ZEND_ENGINE_2_1
++#endif
++#ifdef ZEND_ENGINE_2_1
++#include "zend_vm.h"
 +#endif
-+    }
-+    sma_initialized = 0;
-+    apc_efree(sma_segments);
-+    apc_efree(sma_shmaddrs);
-+}
-+/* }}} */
 +
-+/* {{{ apc_sma_malloc */
-+void* apc_sma_malloc(size_t n)
-+{
-+    int off;
-+    int i;
++#include "rfc1867.h"
 +
-+    TSRMLS_FETCH();
-+    assert(sma_initialized);
-+    LOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
++#endif
 +
-+    off = sma_allocate(sma_shmaddrs[sma_lastseg], n);
-+    if (off != -1) {
-+        void* p = (void *)(((char *)(sma_shmaddrs[sma_lastseg])) + off);
-+        if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
-+        UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
-+        return p;
-+    }
-+    UNLOCK(((header_t*)sma_shmaddrs[sma_lastseg])->sma_lock);
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_pool.c php-5.3.1/ext/apc/apc_pool.c
+--- php-5.3.1.orig/ext/apc/apc_pool.c  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_pool.c       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,484 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2008 The PHP Group                                     |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt.                                 |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
++  +----------------------------------------------------------------------+
 +
-+    for (i = 0; i < sma_numseg; i++) {
-+        if (i == sma_lastseg) {
-+            continue;
-+        }
-+        LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
-+        off = sma_allocate(sma_shmaddrs[i], n);
-+        if (off != -1) {
-+            void* p = (void *)(((char *)(sma_shmaddrs[i])) + off);
-+            if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) += n; }
-+            UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
-+            sma_lastseg = i;
-+            return p;
-+        }
-+        UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
++   This software was contributed to PHP by Yahoo! Inc. in 2008.
++
++   Future revisions and derivatives of this source code must acknowledge
++   Yahoo! Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
++
++   All other licensing and usage conditions are those of the PHP Group.
++
++ */
++
++/* $Id: apc_pool.c 281353 2009-05-28 23:45:08Z kalle $ */
++
++
++#include "apc_pool.h"
++#include <assert.h>
++
++#ifdef HAVE_VALGRIND_MEMCHECK_H
++#include <valgrind/memcheck.h>
++#endif
++
++
++/* {{{ forward references */
++static apc_pool* apc_unpool_create(apc_pool_type type, apc_malloc_t, apc_free_t, apc_protect_t, apc_unprotect_t);
++static apc_pool* apc_realpool_create(apc_pool_type type, apc_malloc_t, apc_free_t, apc_protect_t, apc_unprotect_t);
++/* }}} */
++
++/* {{{ apc_pool_create */
++apc_pool* apc_pool_create(apc_pool_type pool_type, 
++                            apc_malloc_t allocate, 
++                            apc_free_t deallocate,
++                            apc_protect_t protect,
++                            apc_unprotect_t unprotect)
++{
++    if(pool_type == APC_UNPOOL) {
++        return apc_unpool_create(pool_type, allocate, deallocate,
++                                            protect, unprotect );
 +    }
 +
-+    return NULL;
++    return apc_realpool_create(pool_type, allocate, deallocate, 
++                                          protect,  unprotect );
 +}
 +/* }}} */
 +
-+/* {{{ apc_sma_realloc */
-+void* apc_sma_realloc(void *p, size_t n)
++/* {{{ apc_pool_destroy */
++void apc_pool_destroy(apc_pool *pool)
 +{
-+    apc_sma_free(p);
-+    return apc_sma_malloc(n);
++    apc_free_t deallocate = pool->deallocate;
++    apc_pcleanup_t cleanup = pool->cleanup;
++
++    cleanup(pool);
++    deallocate(pool);
 +}
 +/* }}} */
 +
-+/* {{{ apc_sma_strdup */
-+char* apc_sma_strdup(const char* s)
++/* {{{ apc_unpool implementation */
++
++typedef struct _apc_unpool apc_unpool;
++
++struct _apc_unpool {
++    apc_pool parent;
++    /* apc_unpool is a lie! */
++};
++
++static void* apc_unpool_alloc(apc_pool* pool, size_t size) 
 +{
-+    void* q;
-+    int len;
++    apc_unpool *upool = (apc_unpool*)pool;
 +
-+    if(!s) return NULL;
++    apc_malloc_t allocate = upool->parent.allocate;
 +
-+    len = strlen(s)+1;
-+    q = apc_sma_malloc(len);
-+    if(!q) return NULL;
-+    memcpy(q, s, len);
-+    return q;
++    upool->parent.size += size;
++    upool->parent.used += size;
++
++    return allocate(size);
 +}
-+/* }}} */
 +
-+/* {{{ apc_sma_free */
-+void apc_sma_free(void* p)
++static void apc_unpool_free(apc_pool* pool, void *ptr)
 +{
-+    int i;
-+    size_t offset;
-+    size_t d_size;
-+    TSRMLS_FETCH();
-+
-+    if (p == NULL) {
-+        return;
-+    }
++    apc_unpool *upool = (apc_unpool*) pool;
 +
-+    assert(sma_initialized);
++    apc_free_t deallocate = upool->parent.deallocate;
 +
-+    for (i = 0; i < sma_numseg; i++) {
-+        LOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
-+        offset = (size_t)((char *)p - (char *)(sma_shmaddrs[i]));
-+        if (p >= sma_shmaddrs[i] && offset < sma_segsize) {
-+            d_size = sma_deallocate(sma_shmaddrs[i], offset);
-+            if (APCG(mem_size_ptr) != NULL) { *(APCG(mem_size_ptr)) -= d_size; }
-+            UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
-+            return;
-+        }
-+        UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
-+    }
++    deallocate(ptr);
++}
 +
-+    apc_eprint("apc_sma_free: could not locate address %p", p);
++static void apc_unpool_cleanup(apc_pool* pool)
++{
 +}
-+/* }}} */
 +
-+/* {{{ apc_sma_info */
-+apc_sma_info_t* apc_sma_info(zend_bool limited)
++static apc_pool* apc_unpool_create(apc_pool_type type, 
++                    apc_malloc_t allocate, apc_free_t deallocate,
++                    apc_protect_t protect, apc_unprotect_t unprotect)
 +{
-+    apc_sma_info_t* info;
-+    apc_sma_link_t** link;
-+    int i;
-+      char* shmaddr;
-+      block_t* prv;
-+      
-+    if (!sma_initialized) {
++    apc_unpool* upool = allocate(sizeof(apc_unpool));
++
++    if (!upool) {
 +        return NULL;
 +    }
 +
-+    info = (apc_sma_info_t*) apc_emalloc(sizeof(apc_sma_info_t));
-+    info->num_seg = sma_numseg;
-+    info->seg_size = sma_segsize - ALIGNWORD(sizeof(header_t)) - ALIGNWORD(sizeof(block_t));
++    upool->parent.type = type;
++    upool->parent.allocate = allocate;
++    upool->parent.deallocate = deallocate;
 +
-+    info->list = apc_emalloc(info->num_seg * sizeof(apc_sma_link_t*));
-+    for (i = 0; i < sma_numseg; i++) {
-+        info->list[i] = NULL;
-+    }
++    upool->parent.protect = protect;
++    upool->parent.unprotect = unprotect;
 +
-+    if(limited) return info;
++    upool->parent.palloc = apc_unpool_alloc;
++    upool->parent.pfree  = apc_unpool_free;
 +
-+    /* For each segment */
-+    for (i = 0; i < sma_numseg; i++) {
-+        RDLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
-+        shmaddr = sma_shmaddrs[i];
-+        prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
++    upool->parent.cleanup = apc_unpool_cleanup;
 +
-+        link = &info->list[i];
++    upool->parent.used = 0;
++    upool->parent.size = 0;
 +
-+        /* For each block in this segment */
-+        while (prv->next != 0) {
-+            block_t* cur = BLOCKAT(prv->next);
-+#ifdef __APC_SMA_DEBUG__
-+            CHECK_CANARY(cur);
-+#endif
++    return &(upool->parent);
++}
++/* }}} */
 +
-+            *link = apc_emalloc(sizeof(apc_sma_link_t));
-+            (*link)->size = cur->size;
-+            (*link)->offset = prv->next;
-+            (*link)->next = NULL;
-+            link = &(*link)->next;
 +
-+            prv = cur;
-+        }
-+        UNLOCK(((header_t*)sma_shmaddrs[i])->sma_lock);
-+    }
++/*{{{ apc_realpool implementation */
 +
-+    return info;
-+}
-+/* }}} */
++/* {{{ typedefs */
++typedef struct _pool_block
++{
++    size_t              avail;
++    size_t              capacity;
++    unsigned char       *mark;
++    struct _pool_block  *next;
++    unsigned             :0; /* this should align to word */
++    /* data comes here */
++}pool_block;
 +
-+/* {{{ apc_sma_free_info */
-+void apc_sma_free_info(apc_sma_info_t* info)
++/*
++   parts in ? are optional and turned on for fun, memory loss,
++   and for something else that I forgot about ... ah, debugging
++
++                 |--------> data[]         |<-- non word boundary (too)
++   +-------------+--------------+-----------+-------------+-------------->>>
++   | pool_block  | ?sizeinfo<1> | block<1>  | ?redzone<1> | ?sizeinfo<2>
++   |             |  (size_t)    |           | padded left |
++   +-------------+--------------+-----------+-------------+-------------->>>
++ */
++
++typedef struct _apc_realpool apc_realpool;
++
++struct _apc_realpool
 +{
-+    int i;
++    struct _apc_pool parent;
++
++    size_t     dsize;
++    void       *owner;
++
++    pool_block *head;
++    pool_block first; 
++};
 +
-+    for (i = 0; i < info->num_seg; i++) {
-+        apc_sma_link_t* p = info->list[i];
-+        while (p) {
-+            apc_sma_link_t* q = p;
-+            p = p->next;
-+            apc_efree(q);
-+        }
-+    }
-+    apc_efree(info->list);
-+    apc_efree(info);
-+}
 +/* }}} */
 +
-+/* {{{ apc_sma_get_avail_mem */
-+size_t apc_sma_get_avail_mem()
-+{
-+    size_t avail_mem = 0;
-+    int i;
-+    
-+    for (i = 0; i < sma_numseg; i++) {
-+        header_t* header = (header_t*) sma_shmaddrs[i];
-+        avail_mem += header->avail;
-+    }
-+    return avail_mem;
-+}
++/* {{{ redzone code */
++static const unsigned char decaff[] =  {
++    0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad,
++    0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad,
++    0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad,
++    0xde, 0xca, 0xff, 0xc0, 0xff, 0xee, 0xba, 0xad
++};
++
++/* a redzone is at least 4 (0xde,0xca,0xc0,0xff) bytes */
++#define REDZONE_SIZE(size) \
++    ((ALIGNWORD((size)) > ((size) + 4)) ? \
++        (ALIGNWORD((size)) - (size)) : /* does not change realsize */\
++        ALIGNWORD((size)) - (size) + ALIGNWORD((sizeof(char)))) /* adds 1 word to realsize */
++
++#define SIZEINFO_SIZE ALIGNWORD(sizeof(size_t))
++
++#define MARK_REDZONE(block, redsize) do {\
++       memcpy(block, decaff, redsize );\
++    } while(0)
++
++#define CHECK_REDZONE(block, redsize) (memcmp(block, decaff, redsize) == 0)
++
 +/* }}} */
 +
-+#if ALLOC_DISTRIBUTION
-+size_t *apc_sma_get_alloc_distribution(void) {
-+    header_t* header = (header_t*) sma_shmaddrs[0];
-+    return header->adist; 
-+}
-+#endif
++#define INIT_POOL_BLOCK(rpool, entry, size) do {\
++    (entry)->avail = (entry)->capacity = (size);\
++    (entry)->mark =  ((unsigned char*)(entry)) + ALIGNWORD(sizeof(pool_block));\
++    (entry)->next = (rpool)->head;\
++    (rpool)->head = (entry);\
++} while(0)
 +
-+#if 0
-+/* {{{ apc_sma_check_integrity */
-+void apc_sma_check_integrity()
++/* {{{ create_pool_block */
++static pool_block* create_pool_block(apc_realpool *rpool, size_t size)
 +{
-+    int i;
++    apc_malloc_t allocate = rpool->parent.allocate;
 +
-+    /* For each segment */
-+    for (i = 0; i < sma_numseg; i++) {
-+        char* shmaddr = sma_shmaddrs[i];
-+        header_t* header = (header_t*) shmaddr;
-+        block_t* prv = BLOCKAT(ALIGNWORD(sizeof(header_t)));
-+        int avail = 0;
++    size_t realsize = sizeof(pool_block) + ALIGNWORD(size);
 +
-+        /* For each block in this segment */
-+        while (prv->next != 0) {
-+            block_t* cur = BLOCKAT(prv->next);
-+            avail += cur->size;
-+            prv = cur;
-+        }
++    pool_block* entry = allocate(realsize);
 +
-+        assert(avail == header->avail);
++    if (!entry) {
++        return NULL;
 +    }
++
++    INIT_POOL_BLOCK(rpool, entry, size);
++    
++    rpool->parent.size += realsize;
++
++    return entry;
 +}
 +/* }}} */
-+#endif
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_sma.h php-5.2.5/ext/apc/apc_sma.h
---- php-5.2.5-orig/ext/apc/apc_sma.h   1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_sma.h        2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,82 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  +----------------------------------------------------------------------+
++/* {{{ apc_realpool_alloc */
++static void* apc_realpool_alloc(apc_pool *pool, size_t size)
++{
++    apc_realpool *rpool = (apc_realpool*)pool;
++    unsigned char *p = NULL;
++    size_t realsize = ALIGNWORD(size);
++    size_t poolsize;
++    unsigned char *redzone  = NULL;
++    size_t redsize  = 0;
++    size_t *sizeinfo= NULL;
++
++    pool_block *entry;
++
++    if(APC_POOL_HAS_REDZONES(pool)) {
++        redsize = REDZONE_SIZE(size); /* redsize might be re-using word size padding */
++        realsize = size + redsize;    /* recalculating realsize */
++    } else {
++        redsize = realsize - size; /* use padding space */
++    }
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++    if(APC_POOL_HAS_SIZEINFO(pool)) {
++        realsize += ALIGNWORD(sizeof(size_t));
++    }
 +
-+   All other licensing and usage conditions are those of the PHP Group.
 +
-+ */
++    for(entry = rpool->head; entry != NULL; entry = entry->next) {
++        if(entry->avail >= realsize) {
++            goto found;
++        }
++    }
 +
-+/* $Id: apc_sma.h,v 1.18 2007/05/11 01:46:31 shire Exp $ */
++    poolsize = ALIGNSIZE(realsize, rpool->dsize);
 +
-+#ifndef APC_SMA_H
-+#define APC_SMA_H
++    entry = create_pool_block(rpool, poolsize);
 +
-+#define ALLOC_DISTRIBUTION 0
++    if(!entry) {
++        return NULL;
++    }
 +
-+#include "apc.h"
++found:
++    p = entry->mark;
 +
-+/* Simple shared memory allocator */
++    if(APC_POOL_HAS_SIZEINFO(pool)) {
++        sizeinfo = (size_t*)p;
++        p += SIZEINFO_SIZE;
++        *sizeinfo = size;
++    }
 +
-+extern void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask);
-+extern void apc_sma_cleanup();
-+extern void* apc_sma_malloc(size_t size);
-+extern void* apc_sma_realloc(void* p, size_t size);
-+extern char* apc_sma_strdup(const char *s);
-+extern void apc_sma_free(void* p);
-+#if ALLOC_DISTRIBUTION 
-+extern size_t *apc_sma_get_alloc_distribution();
++    redzone = p + size;
++
++    if(APC_POOL_HAS_REDZONES(pool)) {
++        MARK_REDZONE(redzone, redsize);
++    }
++
++#ifdef VALGRIND_MAKE_MEM_NOACCESS
++    if(redsize != 0) {
++        VALGRIND_MAKE_MEM_NOACCESS(redzone, redsize);
++    }
 +#endif
 +
-+/* {{{ struct definition: apc_sma_link_t */
-+typedef struct apc_sma_link_t apc_sma_link_t;
-+struct apc_sma_link_t {
-+    long size;               /* size of this free block */
-+    long offset;             /* offset in segment of this block */
-+    apc_sma_link_t* next;   /* link to next free block */
-+};
-+/* }}} */
++    entry->avail -= realsize;
++    entry->mark  += realsize;
++    pool->used   += realsize;
 +
-+/* {{{ struct definition: apc_sma_info_t */
-+typedef struct apc_sma_info_t apc_sma_info_t;
-+struct apc_sma_info_t {
-+    int num_seg;            /* number of shared memory segments */
-+    long seg_size;           /* size of each shared memory segment */
-+    apc_sma_link_t** list;  /* there is one list per segment */
-+};
++#ifdef VALGRIND_MAKE_MEM_UNDEFINED
++    /* need to write before reading data off this */
++    VALGRIND_MAKE_MEM_UNDEFINED(p, size);
++#endif
++
++    return (void*)p;
++}
 +/* }}} */
 +
-+extern apc_sma_info_t* apc_sma_info(zend_bool limited);
-+extern void apc_sma_free_info(apc_sma_info_t* info);
++/* {{{ apc_realpool_check_integrity */
++/*
++ * Checking integrity at runtime, does an
++ * overwrite check only when the sizeinfo
++ * is set.
++ */
++static int apc_realpool_check_integrity(apc_realpool *rpool) 
++{
++    apc_pool *pool = &(rpool->parent); 
++    pool_block *entry;
++    size_t *sizeinfo = NULL;
++    unsigned char *start;
++    size_t realsize;
++    unsigned char   *redzone;
++    size_t redsize;
++
++    for(entry = rpool->head; entry != NULL; entry = entry->next) {
++        start = (unsigned char *)entry + ALIGNWORD(sizeof(pool_block));
++        if((entry->mark - start) != (entry->capacity - entry->avail)) {
++            return 0;
++        }
++    }
 +
-+extern size_t apc_sma_get_avail_mem();
-+extern void apc_sma_check_integrity();
++    if(!APC_POOL_HAS_REDZONES(pool) ||
++        !APC_POOL_HAS_SIZEINFO(pool)) {
++        return 1;
++    }
 +
++    for(entry = rpool->head; entry != NULL; entry = entry->next) {
++        start = (unsigned char *)entry + ALIGNWORD(sizeof(pool_block));
++
++        while(start < entry->mark) {
++            sizeinfo = (size_t*)start;
++            /* redzone starts where real data ends, in a non-word boundary
++             * redsize is at least 4 bytes + whatever's needed to make it
++             * to another word boundary.
++             */
++            redzone = start + SIZEINFO_SIZE + (*sizeinfo);
++            redsize = REDZONE_SIZE(*sizeinfo);
++#ifdef VALGRIND_MAKE_MEM_DEFINED
++            VALGRIND_MAKE_MEM_DEFINED(redzone, redsize);
++#endif
++            if(!CHECK_REDZONE(redzone, redsize))
++            {
++                /*
++                fprintf(stderr, "Redzone check failed for %p\n", 
++                                start + ALIGNWORD(sizeof(size_t)));*/
++                return 0;
++            }
++#ifdef VALGRIND_MAKE_MEM_NOACCESS
++            VALGRIND_MAKE_MEM_NOACCESS(redzone, redsize);
 +#endif
++            realsize = SIZEINFO_SIZE + *sizeinfo + redsize;
++            start += realsize;
++        }
++    }
++
++    return 1;
++}
++/* }}} */
++
++/* {{{ apc_pool_free */
++/*
++ * free does not do anything other than
++ * check for redzone values when free'ing
++ * data areas.
++ */
++static void apc_realpool_free(apc_pool *pool, void *p)
++{
++}
++/* }}} */
++
++static void apc_realpool_cleanup(apc_pool *pool) 
++{
++    pool_block *entry;
++    pool_block *tmp;
++    apc_realpool *rpool = (apc_realpool*)pool;
++    apc_free_t deallocate = pool->deallocate;
++
++    assert(apc_realpool_check_integrity(rpool)!=0);
++
++    entry = rpool->head;
++
++    while(entry->next != NULL) {
++        tmp = entry->next;
++        deallocate(entry);
++        entry = tmp;
++    }
++}
++
++/* {{{ apc_realpool_create */
++static apc_pool* apc_realpool_create(apc_pool_type type, apc_malloc_t allocate, apc_free_t deallocate, 
++                                                         apc_protect_t protect, apc_unprotect_t unprotect)
++{
++
++    size_t dsize = 0;
++    apc_realpool *rpool;
++
++    switch(type & APC_POOL_SIZE_MASK) {
++        case APC_SMALL_POOL:
++            dsize = 512;
++            break;
++
++        case APC_LARGE_POOL:
++            dsize = 8192;
++            break;
++
++        case APC_MEDIUM_POOL:
++            dsize = 4096;
++            break;
++
++        default:
++            return NULL;
++    }
++
++    rpool = (apc_realpool*)allocate(sizeof(apc_realpool) + ALIGNWORD(dsize));
++
++    if(!rpool) {
++        return NULL;
++    }
++
++    rpool->parent.type = type;
++
++    rpool->parent.allocate = allocate;
++    rpool->parent.deallocate = deallocate;
++
++    rpool->parent.size = sizeof(apc_realpool) + ALIGNWORD(dsize);
++
++    rpool->parent.palloc = apc_realpool_alloc;
++    rpool->parent.pfree  = apc_realpool_free;
++
++    rpool->parent.protect = protect;
++    rpool->parent.unprotect = unprotect;
++
++    rpool->parent.cleanup = apc_realpool_cleanup;
++
++    rpool->dsize = dsize;
++    rpool->head = NULL;
++
++    INIT_POOL_BLOCK(rpool, &(rpool->first), dsize);
++
++    return &(rpool->parent);
++}
++
++
++/* }}} */
++
++/* {{{ apc_pool_init */
++void apc_pool_init()
++{
++    /* put all ye sanity checks here */
++    assert(sizeof(decaff) > REDZONE_SIZE(ALIGNWORD(sizeof(char))));
++    assert(sizeof(pool_block) == ALIGNWORD(sizeof(pool_block)));
++    assert((APC_POOL_SIZE_MASK & (APC_POOL_SIZEINFO | APC_POOL_REDZONES)) == 0);
++}
++/* }}} */
++
++/* {{{ apc_pstrdup */
++void* apc_pstrdup(const char* s, apc_pool* pool)
++{
++    return s != NULL ? apc_pmemcpy(s, strlen(s)+1, pool) : NULL;
++}
++/* }}} */
++
++/* {{{ apc_pmemcpy */
++void* apc_pmemcpy(const void* p, size_t n, apc_pool* pool)
++{
++    void* q;
++
++    if (p != NULL && (q = apc_pool_alloc(pool, n)) != NULL) {
++        memcpy(q, p, n);
++        return q;
++    }
++    return NULL;
++}
++/* }}} */
 +
 +/*
 + * Local variables:
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_spin.c php-5.2.5/ext/apc/apc_spin.c
---- php-5.2.5-orig/ext/apc/apc_spin.c  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_spin.c       2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,65 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_pool.h php-5.3.1/ext/apc/apc_pool.h
+--- php-5.3.1.orig/ext/apc/apc_pool.h  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_pool.h       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,102 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2008 The PHP Group                                     |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt.                                 |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Gopal Vijayaraghavan <gopalv@yahoo-inc.com>                 |
++  +----------------------------------------------------------------------+
++
++   This software was contributed to PHP by Yahoo! Inc. in 2008.
++
++   Future revisions and derivatives of this source code must acknowledge
++   Yahoo! Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
++
++   All other licensing and usage conditions are those of the PHP Group.
++
++ */
++
++/* $Id: apc_pool.h 275212 2009-02-05 08:36:26Z gopalv $ */
++
++#ifndef APC_POOL_H
++#define APC_POOL_H
++
++#include "apc.h"
++#include "apc_sma.h"
++
++typedef enum {
++    APC_UNPOOL         = 0x0,
++    APC_SMALL_POOL     = 0x1,
++    APC_MEDIUM_POOL    = 0x2,
++    APC_LARGE_POOL     = 0x3,
++    APC_POOL_SIZE_MASK = 0x7,   /* waste a bit */
++    APC_POOL_REDZONES  = 0x08,
++    APC_POOL_SIZEINFO  = 0x10,
++    APC_POOL_OPT_MASK  = 0x18
++} apc_pool_type;
++
++#define APC_POOL_HAS_SIZEINFO(pool) ((pool->type & APC_POOL_SIZEINFO)!=0)
++#define APC_POOL_HAS_REDZONES(pool) ((pool->type & APC_POOL_REDZONES)!=0)
++
++typedef struct _apc_pool apc_pool;
++
++typedef void  (*apc_pcleanup_t)(apc_pool *pool);
++
++typedef void* (*apc_palloc_t)(apc_pool *pool, size_t size);
++typedef void  (*apc_pfree_t) (apc_pool *pool, void* p);
++
++typedef void* (*apc_protect_t)  (void *p);
++typedef void* (*apc_unprotect_t)(void *p);
++
++struct _apc_pool {
++    apc_pool_type   type;
++
++    apc_malloc_t    allocate;
++    apc_free_t      deallocate;
++
++    apc_palloc_t    palloc;
++    apc_pfree_t     pfree;
++
++      apc_protect_t   protect;
++      apc_unprotect_t unprotect;
++
++    apc_pcleanup_t  cleanup;
++
++    size_t          size;
++    size_t          used;
++
++    /* apc_realpool and apc_unpool add more here */
++};
++
++#define apc_pool_alloc(pool, size) ((pool)->palloc((pool), (size)))
++#define apc_pool_free (pool, ptr)  ((pool)->pfree((pool), (ptr)))
++
++#define apc_pool_protect (pool, ptr)  (pool->protect ? \
++                                                                              (pool)->protect((ptr)) : (ptr))
++
++#define apc_pool_unprotect (pool, ptr)  (pool->unprotect ? \
++                                                                                      (pool)->unprotect((ptr)) : (ptr))
++
++extern void apc_pool_init();
++
++extern apc_pool* apc_pool_create(apc_pool_type pool_type,
++                            apc_malloc_t allocate,
++                            apc_free_t deallocate,
++                                                      apc_protect_t protect,
++                                                      apc_unprotect_t unprotect);
++
++extern void apc_pool_destroy(apc_pool* pool);
++
++extern void* apc_pmemcpy(const void* p, size_t n, apc_pool* pool);
++extern void* apc_pstrdup(const char* s, apc_pool* pool);
++
++#endif
+diff -Naur php-5.3.1.orig/ext/apc/apc_pthreadmutex.c php-5.3.1/ext/apc/apc_pthreadmutex.c
+--- php-5.3.1.orig/ext/apc/apc_pthreadmutex.c  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_pthreadmutex.c       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,111 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2007 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -10080,39 +10204,85 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_spin.c php-5.2.5/ext/apc/apc_spin.c
 +
 + */
 +
-+/* $Id: apc_spin.c,v 3.1 2007/01/29 07:39:02 shire Exp $ */
++/* $Id: apc_pthreadmutex.c 268255 2008-11-04 05:42:11Z rasmus $ */
 +
-+#include "apc_spin.h"
++#include "apc_pthreadmutex.h"
 +
-+#ifdef APC_SPIN_LOCKS
++#ifdef APC_PTHREADMUTEX_LOCKS
 +
-+slock_t *apc_slock_create(slock_t *lock) 
++pthread_mutex_t *apc_pthreadmutex_create(pthread_mutex_t *lock) 
 +{
-+   S_INIT_LOCK(lock); 
++    int result;
++    pthread_mutexattr_t* attr;
++    attr = malloc(sizeof(pthread_mutexattr_t));
++
++    result = pthread_mutexattr_init(attr);
++    if(result == ENOMEM) {
++        apc_eprint("pthread mutex error: Insufficient memory exists to create the mutex attribute object.");
++    } else if(result == EINVAL) {
++        apc_eprint("pthread mutex error: attr does not point to writeable memory.");
++    } else if(result == EFAULT) {
++        apc_eprint("pthread mutex error: attr is an invalid pointer.");
++    }
++
++#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
++       result = pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ADAPTIVE_NP);
++       if (result == EINVAL) {
++               apc_eprint("pthread_mutexattr_settype: unable to set adaptive mutexes");
++       }
++#endif
++
++    /* pthread_mutexattr_settype(attr, PTHREAD_MUTEX_ERRORCHECK); */
++    result = pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED);
++    if(result == EINVAL) {
++        apc_eprint("pthread mutex error: attr is not an initialized mutex attribute object, or pshared is not a valid process-shared state setting.");
++    } else if(result == EFAULT) {
++        apc_eprint("pthread mutex error: attr is an invalid pointer.");
++    } else if(result == ENOTSUP) {
++        apc_eprint("pthread mutex error: pshared was set to PTHREAD_PROCESS_SHARED.");
++    }
++
++    if(pthread_mutex_init(lock, attr)) { 
++        apc_eprint("unable to initialize pthread lock");
++    }
++    return lock;
 +}
 +
-+void apc_slock_destroy(slock_t *lock)
++void apc_pthreadmutex_destroy(pthread_mutex_t *lock)
 +{
-+    S_LOCK_FREE(lock);
++    return; /* we don't actually destroy the mutex, as it would destroy it for all processes */
 +}
 +
-+void apc_slock_lock(slock_t *lock)
++void apc_pthreadmutex_lock(pthread_mutex_t *lock)
 +{
-+    S_LOCK(lock);
++    int result;
++    result = pthread_mutex_lock(lock);
++    if(result == EINVAL) {
++        apc_eprint("unable to obtain pthread lock (EINVAL)");
++    } else if(result == EDEADLK) {
++        apc_eprint("unable to obtain pthread lock (EDEADLK)");
++    }
 +}
 +
-+void apc_slock_unlock(slock_t *lock)
++void apc_pthreadmutex_unlock(pthread_mutex_t *lock)
 +{
-+    S_UNLOCK(lock);
++    if(pthread_mutex_unlock(lock)) {
++        apc_eprint("unable to unlock pthread lock");
++    }
 +}
 +
-+zend_bool apc_slock_nonblocking_lock(slock_t *lock)
++zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock)
 +{
-+    /* Technically we aren't supposed to call this directly, but the original
-+     *  code provides no method for absolute non-blocking locks, so we'll call into
-+     *  the TAS (test and set) functionality directly 
-+     */
-+    return !(TAS(lock));  /* if TAS returns 0 we obtained the lock, otherwise we failed */
++    int rval;
++    rval = pthread_mutex_trylock(lock);
++    if(rval == EBUSY) {     /* Lock is already held */
++        return 0;
++    } else if(rval == 0) {  /* Obtained lock */
++        return 1;
++    } else {                /* Other error */
++        apc_eprint("unable to obtain pthread trylock");
++        return 0;
++    }
 +}
 +
 +
@@ -10123,18 +10293,18 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_spin.c php-5.2.5/ext/apc/apc_spin.c
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_spin.h php-5.2.5/ext/apc/apc_spin.h
---- php-5.2.5-orig/ext/apc/apc_spin.h  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_spin.h       2007-12-26 16:51:32.000000000 -0600
+diff -Naur php-5.3.1.orig/ext/apc/apc_pthreadmutex.h php-5.3.1/ext/apc/apc_pthreadmutex.h
+--- php-5.3.1.orig/ext/apc/apc_pthreadmutex.h  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_pthreadmutex.h       1970-01-01 10:13:08.000000000 +0100
 @@ -0,0 +1,48 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2007 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -10149,22 +10319,22 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_spin.h php-5.2.5/ext/apc/apc_spin.h
 +
 + */
 +
-+/* $Id: apc_spin.h,v 3.1 2007/01/29 07:39:02 shire Exp $ */
++/* $Id: apc_pthreadmutex.h 268255 2008-11-04 05:42:11Z rasmus $ */
 +
-+#ifndef APC_SPIN_H
-+#define APC_SPIN_H
++#ifndef APC_PTHREADMUTEX_H
++#define APC_PTHREADMUTEX_H
 +
 +#include "apc.h"
 +
-+#ifdef APC_SPIN_LOCKS 
++#ifdef APC_PTHREADMUTEX_LOCKS
 +
-+#include "pgsql_s_lock.h"
++#include <pthread.h>
 +
-+pthread_mutex_t *apc_spin_create();
-+void apc_spin_destroy(pthread_mutex_t *lock);
-+void apc_spin_lock(pthread_mutex_t *lock);
-+void apc_spin_unlock(pthread_mutex_t *lock);
-+zend_bool apc_spin_nonblocking_lock(pthread_mutex_t *lock);
++pthread_mutex_t *apc_pthreadmutex_create();
++void apc_pthreadmutex_destroy(pthread_mutex_t *lock);
++void apc_pthreadmutex_lock(pthread_mutex_t *lock);
++void apc_pthreadmutex_unlock(pthread_mutex_t *lock);
++zend_bool apc_pthreadmutex_nonblocking_lock(pthread_mutex_t *lock);
 +
 +#endif
 +
@@ -10175,18 +10345,18 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_spin.h php-5.2.5/ext/apc/apc_spin.h
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_stack.c php-5.2.5/ext/apc/apc_stack.c
---- php-5.2.5-orig/ext/apc/apc_stack.c 1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_stack.c      2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,105 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_rfc1867.c php-5.3.1/ext/apc/apc_rfc1867.c
+--- php-5.3.1.orig/ext/apc/apc_rfc1867.c       1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_rfc1867.c    1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,214 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -10196,7 +10366,7 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_stack.c php-5.2.5/ext/apc/apc_stack.c
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  | Authors: Rasmus Lerdorf <rasmus@php.net>                             |
 +  +----------------------------------------------------------------------+
 +
 +   This software was contributed to PHP by Community Connect Inc. in 2002
@@ -10209,155 +10379,202 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_stack.c php-5.2.5/ext/apc/apc_stack.c
 +
 + */
 +
-+/* $Id: apc_stack.c,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
++/* $Id: apc_rfc1867.c 284580 2009-07-22 06:05:31Z kalle $*/
 +
-+#include "apc_stack.h"
 +#include "apc.h"
++#include "apc_globals.h"
++#include "rfc1867.h"
 +
-+struct apc_stack_t {
-+    void** data;
-+    int capacity;
-+    int size;
-+};
++#ifdef PHP_WIN32
++#include "win32/time.h"
++#endif
 +
-+apc_stack_t* apc_stack_create(int size_hint)
-+{
-+    apc_stack_t* stack = (apc_stack_t*) apc_emalloc(sizeof(apc_stack_t));
++#ifdef MULTIPART_EVENT_FORMDATA
++extern int _apc_store(char *strkey, int strkey_len, const zval *val, const uint ttl, const int exclusive TSRMLS_DC);
++extern int _apc_update(char *strkey, int strkey_len, apc_cache_updater_t updater, void* data TSRMLS_DC);
++
++static int update_bytes_processed(apc_cache_t* cache, apc_cache_entry_t* entry, void* data) {
++    int *bytes_ptr = (int*)data;
++    zval* val = entry->data.user.val;
++
++    if(Z_TYPE_P(val) == IS_ARRAY) {
++        HashTable *ht = val->value.ht;
++        Bucket* curr = NULL;
++        for (curr = ht->pListHead; curr != NULL; curr = curr->pListNext) {
++            if(curr->nKeyLength == 8 && 
++                (!memcmp(curr->arKey, "current", curr->nKeyLength))) {
++                zval* current =  ((zval**)curr->pData)[0];
++                current->value.lval = *bytes_ptr;
++                return 1;
++            }
++        }
++    }
 +
-+    stack->capacity = (size_hint > 0) ? size_hint : 10;
-+    stack->size = 0;
-+    stack->data = (void**) apc_emalloc(sizeof(void*) * stack->capacity);
++    return 0;
++}
 +
-+    return stack;
++static double my_time() {
++    struct timeval a;
++    double t;
++    gettimeofday(&a, NULL);
++    t = a.tv_sec + (a.tv_usec/1000000.00);
++    return t;
 +}
 +
-+void apc_stack_destroy(apc_stack_t* stack)
-+{
-+    if (stack != NULL) {
-+        apc_efree(stack->data);
-+        apc_efree(stack);
-+    }
-+}
-+
-+void apc_stack_clear(apc_stack_t* stack)
-+{
-+    assert(stack != NULL);
-+    stack->size = 0;
-+}
-+
-+void apc_stack_push(apc_stack_t* stack, void* item)
-+{
-+    assert(stack != NULL);
-+    if (stack->size == stack->capacity) {
-+        stack->capacity *= 2;
-+        stack->data = apc_erealloc(stack->data, sizeof(void*)*stack->capacity);
-+    }
-+    stack->data[stack->size++] = item;
-+}
-+
-+void* apc_stack_pop(apc_stack_t* stack)
-+{
-+    assert(stack != NULL && stack->size > 0);
-+    return stack->data[--stack->size];
-+}
-+
-+void* apc_stack_top(apc_stack_t* stack)
-+{
-+    assert(stack != NULL && stack->size > 0);
-+    return stack->data[stack->size-1];
-+}
 +
-+void* apc_stack_get(apc_stack_t* stack, int n)
-+{
-+    assert(stack != NULL && stack->size > n);
-+    return stack->data[n];
-+}
++#define RFC1867_DATA(name) \
++                ((request_data)->name)
 +
-+int apc_stack_size(apc_stack_t* stack)
-+{
-+    assert(stack != NULL);
-+    return stack->size;
-+}
++int apc_rfc1867_progress(uint event, void *event_data, void **extra TSRMLS_DC) {
++    apc_rfc1867_data *request_data = &APCG(rfc1867_data);
++    zval *track = NULL;
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_stack.h php-5.2.5/ext/apc/apc_stack.h
---- php-5.2.5-orig/ext/apc/apc_stack.h 1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_stack.h      2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,58 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          George Schlossnagle <george@omniti.com>                     |
-+  +----------------------------------------------------------------------+
++    switch (event) {
++        case MULTIPART_EVENT_START:
++            {
++                multipart_event_start *data = (multipart_event_start *) event_data;
++                
++                RFC1867_DATA(content_length)    = data->content_length;
++                RFC1867_DATA(tracking_key)[0]   = '\0';
++                RFC1867_DATA(name)[0]           = '\0';
++                RFC1867_DATA(cancel_upload)     = 0;
++                RFC1867_DATA(temp_filename)     = NULL;
++                RFC1867_DATA(filename)[0]       = '\0';
++                RFC1867_DATA(key_length)        = 0;
++                RFC1867_DATA(start_time)        = my_time();
++                RFC1867_DATA(bytes_processed)   = 0;
++                RFC1867_DATA(rate)              = 0;
++                RFC1867_DATA(update_freq)       = (int) APCG(rfc1867_freq);
++                
++                if(RFC1867_DATA(update_freq) < 0) {  // frequency is a percentage, not bytes
++                    RFC1867_DATA(update_freq) = (int) (RFC1867_DATA(content_length) * APCG(rfc1867_freq) / 100); 
++                }
++            }
++            break;
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++        case MULTIPART_EVENT_FORMDATA:
++            {
++                int prefix_len = strlen(APCG(rfc1867_prefix));
++                multipart_event_formdata *data = (multipart_event_formdata *) event_data;
++                if(data->name && !strncasecmp(data->name, APCG(rfc1867_name), strlen(APCG(rfc1867_name))) 
++                    && data->value && data->length && data->length < sizeof(RFC1867_DATA(tracking_key)) - prefix_len) {
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++                    strlcat(RFC1867_DATA(tracking_key), APCG(rfc1867_prefix), 63);
++                    strlcat(RFC1867_DATA(tracking_key), *data->value, 63);
++                    RFC1867_DATA(key_length) = data->length + prefix_len;
++                    RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
++                }
++            }
++            break;
 +
-+ */
++        case MULTIPART_EVENT_FILE_START:
++            if(*RFC1867_DATA(tracking_key)) {
++                multipart_event_file_start *data = (multipart_event_file_start *) event_data;
 +
-+/* $Id: apc_stack.h,v 3.4 2006/03/12 00:31:45 rasmus Exp $ */
++                RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
++                strncpy(RFC1867_DATA(filename),*data->filename,127);
++                RFC1867_DATA(temp_filename) = NULL;
++                strncpy(RFC1867_DATA(name),data->name,63);
++                ALLOC_INIT_ZVAL(track);
++                array_init(track);
++                add_assoc_long(track, "total", RFC1867_DATA(content_length));
++                add_assoc_long(track, "current", RFC1867_DATA(bytes_processed));
++                add_assoc_string(track, "filename", RFC1867_DATA(filename), 1);
++                add_assoc_string(track, "name", RFC1867_DATA(name), 1);
++                add_assoc_long(track, "done", 0);
++                add_assoc_double(track, "start_time", RFC1867_DATA(start_time));
++                _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length), track, 3600, 0 TSRMLS_CC);
++                zval_ptr_dtor(&track);
++            }
++            break;
 +
-+#ifndef APC_STACK_H
-+#define APC_STACK_H
++        case MULTIPART_EVENT_FILE_DATA:
++            if(*RFC1867_DATA(tracking_key)) {
++                multipart_event_file_data *data = (multipart_event_file_data *) event_data;
++                RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
++                if(RFC1867_DATA(bytes_processed) - RFC1867_DATA(prev_bytes_processed) > (uint) RFC1867_DATA(update_freq)) {
++                    if(!_apc_update(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length), update_bytes_processed, &RFC1867_DATA(bytes_processed) TSRMLS_CC)) {
++                        ALLOC_INIT_ZVAL(track);
++                        array_init(track);
++                        add_assoc_long(track, "total", RFC1867_DATA(content_length));
++                        add_assoc_long(track, "current", RFC1867_DATA(bytes_processed));
++                        add_assoc_string(track, "filename", RFC1867_DATA(filename), 1);
++                        add_assoc_string(track, "name", RFC1867_DATA(name), 1);
++                        add_assoc_long(track, "done", 0);
++                        add_assoc_double(track, "start_time", RFC1867_DATA(start_time));
++                        _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length), track, 3600, 0 TSRMLS_CC);
++                        zval_ptr_dtor(&track);
++                    }
++                    RFC1867_DATA(prev_bytes_processed) = RFC1867_DATA(bytes_processed);
++                }
++            }
++            break;
 +
-+/* Basic stack datatype */
++        case MULTIPART_EVENT_FILE_END:
++            if(*RFC1867_DATA(tracking_key)) {
++                multipart_event_file_end *data = (multipart_event_file_end *) event_data;
++                RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
++                RFC1867_DATA(cancel_upload) = data->cancel_upload;
++                RFC1867_DATA(temp_filename) = data->temp_filename;
++                ALLOC_INIT_ZVAL(track);
++                array_init(track);
++                add_assoc_long(track, "total", RFC1867_DATA(content_length));
++                add_assoc_long(track, "current", RFC1867_DATA(bytes_processed));
++                add_assoc_string(track, "filename", RFC1867_DATA(filename), 1);
++                add_assoc_string(track, "name", RFC1867_DATA(name), 1);
++                add_assoc_string(track, "temp_filename", RFC1867_DATA(temp_filename), 1);
++                add_assoc_long(track, "cancel_upload", RFC1867_DATA(cancel_upload));
++                add_assoc_long(track, "done", 0);
++                add_assoc_double(track, "start_time", RFC1867_DATA(start_time));
++                _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length), track, 3600, 0 TSRMLS_CC);
++                zval_ptr_dtor(&track);
++            }
++            break;
 +
-+#define T apc_stack_t*
-+typedef struct apc_stack_t apc_stack_t; /* opaque stack type */
++        case MULTIPART_EVENT_END:
++            if(*RFC1867_DATA(tracking_key)) {
++                double now = my_time(); 
++                multipart_event_end *data = (multipart_event_end *) event_data;
++                RFC1867_DATA(bytes_processed) = data->post_bytes_processed;
++                if(now>RFC1867_DATA(start_time)) RFC1867_DATA(rate) = 8.0*RFC1867_DATA(bytes_processed)/(now-RFC1867_DATA(start_time));
++                else RFC1867_DATA(rate) = 8.0*RFC1867_DATA(bytes_processed);  /* Too quick */
++                ALLOC_INIT_ZVAL(track);
++                array_init(track);
++                add_assoc_long(track, "total", RFC1867_DATA(content_length));
++                add_assoc_long(track, "current", RFC1867_DATA(bytes_processed));
++                add_assoc_double(track, "rate", RFC1867_DATA(rate));
++                add_assoc_string(track, "filename", RFC1867_DATA(filename), 1);
++                add_assoc_string(track, "name", RFC1867_DATA(name), 1);
++                add_assoc_long(track, "cancel_upload", RFC1867_DATA(cancel_upload));
++                add_assoc_long(track, "done", 1);
++                add_assoc_double(track, "start_time", RFC1867_DATA(start_time));
++                _apc_store(RFC1867_DATA(tracking_key), RFC1867_DATA(key_length), track, APCG(rfc1867_ttl), 0 TSRMLS_CC);
++                zval_ptr_dtor(&track);
++            }
++            break;
++    }
 +
-+extern T apc_stack_create(int size_hint);
-+extern void apc_stack_destroy(T stack);
-+extern void apc_stack_clear(T stack);
-+extern void apc_stack_push(T stack, void* item);
-+extern void* apc_stack_pop(T stack);
-+extern void* apc_stack_top(T stack);
-+extern void* apc_stack_get(T stack, int n);
-+extern int apc_stack_size(T stack);
++    return SUCCESS;
++}
 +
-+#undef T
 +#endif
-+
 +/*
 + * Local variables:
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_zend.c php-5.2.5/ext/apc/apc_zend.c
---- php-5.2.5-orig/ext/apc/apc_zend.c  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_zend.c       2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,277 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_sem.c php-5.3.1/ext/apc/apc_sem.c
+--- php-5.3.1.orig/ext/apc/apc_sem.c   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_sem.c        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,201 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -10380,265 +10597,189 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_zend.c php-5.2.5/ext/apc/apc_zend.c
 +
 + */
 +
-+/* $Id: apc_zend.c,v 3.14 2007/04/02 22:57:10 rasmus Exp $ */
++/* $Id: apc_sem.c 268620 2008-11-09 02:30:49Z shire $ */
 +
-+#include "apc_zend.h"
-+#include "apc_globals.h"
++#include "apc.h"
 +
-+void* apc_php_malloc(size_t n)
-+{
-+    return emalloc(n);
-+}
++#ifdef APC_SEM_LOCKS
 +
-+void apc_php_free(void* p)
-+{
-+    efree(p);
-+}
++#include "apc_sem.h"
++#include "php.h"
++#include <sys/types.h>
++#include <sys/ipc.h>
++#include <sys/sem.h>
++#include <sys/stat.h>
++#include <unistd.h>
 +
-+#ifndef ZEND_VM_KIND_CALL /* Not currently defined by any ZE version */
-+# define ZEND_VM_KIND_CALL    1
++#if HAVE_SEMUN
++/* we have semun, no need to define */
++#else
++#undef HAVE_SEMUN
++union semun {
++    int val;                  /* value for SETVAL */
++    struct semid_ds *buf;     /* buffer for IPC_STAT, IPC_SET */
++    unsigned short *array;    /* array for GETALL, SETALL */
++                              /* Linux specific part: */
++    struct seminfo *__buf;    /* buffer for IPC_INFO */
++};
++#define HAVE_SEMUN 1
 +#endif
 +
-+#ifndef ZEND_VM_KIND /* Indicates PHP < 5.1 */
-+# define ZEND_VM_KIND ZEND_VM_KIND_CALL
++#ifndef SEM_R
++# define SEM_R 0444
 +#endif
-+
-+#if defined(ZEND_ENGINE_2) && (ZEND_VM_KIND == ZEND_VM_KIND_CALL)
-+# define APC_OPCODE_OVERRIDE
++#ifndef SEM_A
++# define SEM_A 0222
 +#endif
 +
-+#ifdef APC_OPCODE_OVERRIDE
-+
-+#ifdef ZEND_ENGINE_2_1
-+/* Taken from Zend/zend_vm_execute.h */
-+#define _CONST_CODE  0
-+#define _TMP_CODE    1
-+#define _VAR_CODE    2
-+#define _UNUSED_CODE 3
-+#define _CV_CODE     4
-+static inline int _apc_opcode_handler_decode(zend_op *opline)
-+{
-+      static const int apc_vm_decode[] = {
-+              _UNUSED_CODE, /* 0              */
-+              _CONST_CODE,  /* 1 = IS_CONST   */
-+              _TMP_CODE,    /* 2 = IS_TMP_VAR */
-+              _UNUSED_CODE, /* 3              */
-+              _VAR_CODE,    /* 4 = IS_VAR     */
-+              _UNUSED_CODE, /* 5              */
-+              _UNUSED_CODE, /* 6              */
-+              _UNUSED_CODE, /* 7              */
-+              _UNUSED_CODE, /* 8 = IS_UNUSED  */
-+              _UNUSED_CODE, /* 9              */
-+              _UNUSED_CODE, /* 10             */
-+              _UNUSED_CODE, /* 11             */
-+              _UNUSED_CODE, /* 12             */
-+              _UNUSED_CODE, /* 13             */
-+              _UNUSED_CODE, /* 14             */
-+              _UNUSED_CODE, /* 15             */
-+              _CV_CODE      /* 16 = IS_CV     */
-+      };
-+      return (opline->opcode * 25) + (apc_vm_decode[opline->op1.op_type] * 5) + apc_vm_decode[opline->op2.op_type];
-+}
-+
-+# define APC_ZEND_OPLINE                                      zend_op *opline = execute_data->opline;
-+# define APC_OPCODE_HANDLER_DECODE(opline)    _apc_opcode_handler_decode(opline)
-+# if PHP_MAJOR_VERSION >= 6
-+#  define APC_OPCODE_HANDLER_COUNT                    ((25 * 152) + 1)
-+# else
-+#  define APC_OPCODE_HANDLER_COUNT                    ((25 * 151) + 1)
-+# endif
-+# define APC_REPLACE_OPCODE(opname)         { int i; for(i = 0; i < 25; i++) if (zend_opcode_handlers[(opname*25) + i]) zend_opcode_handlers[(opname*25) + i] = apc_op_##opname; }
++/* always use SEM_UNDO, otherwise we risk deadlock */
++#define USE_SEM_UNDO
 +
-+#else /* ZE2.0 */
-+# define APC_ZEND_ONLINE
-+# define APC_OPCODE_HANDLER_DECODE(opline)    (opline->opcode)
-+# define APC_OPCODE_HANDLER_COUNT                     512
-+# define APC_REPLACE_OPCODE(opname)                   zend_opcode_handlers[opname] = apc_op_##opname;
++#ifdef USE_SEM_UNDO
++# define UNDO SEM_UNDO
++#else
++# define UNDO 0
 +#endif
 +
-+static opcode_handler_t *apc_original_opcode_handlers;
-+static opcode_handler_t apc_opcode_handlers[APC_OPCODE_HANDLER_COUNT];
++int apc_sem_create(const char* pathname, int proj, int initval)
++{
++    int semid;
++    int perms;
++    union semun arg;
++    key_t key;
 +
-+#define APC_EX_T(offset)                                      (*(temp_variable *)((char*)execute_data->Ts + offset))
++    perms = 0777;
 +
-+static zval *apc_get_zval_ptr(znode *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC)
-+{
-+      *freeval = NULL;
++    key = IPC_PRIVATE;
++    if (pathname != NULL) {
++        if ((key = ftok(pathname, proj)) < 0) {
++            apc_eprint("apc_sem_create: ftok(%s,%d) failed:", pathname, proj);
++        }
++    }
 +
-+      switch (node->op_type) {
-+              case IS_CONST:
-+                      return &(node->u.constant);
-+              case IS_VAR:
-+                      return APC_EX_T(node->u.var).var.ptr;
-+              case IS_TMP_VAR:
-+                      return (*freeval = &APC_EX_T(node->u.var).tmp_var);
-+#ifdef ZEND_ENGINE_2_1
-+              case IS_CV:
-+              {
-+                      zval ***ret = &execute_data->CVs[node->u.var];
++    if ((semid = semget(key, 1, IPC_CREAT | IPC_EXCL | perms)) >= 0) {
++        /* sempahore created for the first time, initialize now */
++        arg.val = initval;
++        if (semctl(semid, 0, SETVAL, arg) < 0) {
++            apc_eprint("apc_sem_create: semctl(%d,...) failed:", semid);
++        }
++    }
++    else if (errno == EEXIST) {
++        /* sempahore already exists, don't initialize */
++        if ((semid = semget(key, 1, perms)) < 0) {
++            apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
++        }
++        /* insert <sleazy way to avoid race condition> here */
++    }
++    else {
++        apc_eprint("apc_sem_create: semget(%u,...) failed:", key);
++    }
 +
-+                      if (!*ret) {
-+                              zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var];
++    return semid;
++}
 +
-+                              if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) {
-+                                      apc_nprint("Undefined variable: %s", cv->name);
-+                                      return &EG(uninitialized_zval);
-+                              }
-+                      }
-+                      return **ret;
-+              }
-+#endif
-+              case IS_UNUSED:
-+              default:
-+                      return NULL;
-+      }
++void apc_sem_destroy(int semid)
++{
++    /* we expect this call to fail often, so we do not check */
++    union semun arg;
++    semctl(semid, 0, IPC_RMID, arg);
 +}
 +
-+static int apc_op_ZEND_INCLUDE_OR_EVAL(ZEND_OPCODE_HANDLER_ARGS)
++void apc_sem_lock(int semid)
 +{
-+      APC_ZEND_OPLINE
-+      zval *freeop1 = NULL;
-+      zval *inc_filename = NULL, tmp_inc_filename;
-+      char realpath[MAXPATHLEN];
-+      php_stream_wrapper *wrapper;
-+      char *path_for_open;
-+      int ret = 0;
-+      #ifdef ZEND_ENGINE_2
-+      apc_opflags_t* flags = NULL;
-+      #endif
++    struct sembuf op;
 +
-+      if (Z_LVAL(opline->op2.u.constant) != ZEND_INCLUDE_ONCE &&
-+              Z_LVAL(opline->op2.u.constant) != ZEND_REQUIRE_ONCE) {
-+              return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-+      }
++    op.sem_num = 0;
++    op.sem_op  = -1;
++    op.sem_flg = UNDO;
 +
-+      inc_filename = apc_get_zval_ptr(&opline->op1, &freeop1, execute_data TSRMLS_CC);
-+      if (Z_TYPE_P(inc_filename) != IS_STRING) {
-+              tmp_inc_filename = *inc_filename;
-+              zval_copy_ctor(&tmp_inc_filename);
-+              convert_to_string(&tmp_inc_filename);
-+              inc_filename = &tmp_inc_filename;
-+      }
-+
-+      wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(inc_filename), &path_for_open, 0 TSRMLS_CC);
-+      if (wrapper != &php_plain_files_wrapper ||
-+              !IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) ||
-+              !expand_filepath(path_for_open, realpath TSRMLS_CC)) {
-+              /* Fallback to original handler */
-+              if (inc_filename == &tmp_inc_filename) {
-+                      zval_dtor(&tmp_inc_filename);
-+              }
-+              return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-+      }
-+
-+      if (zend_hash_exists(&EG(included_files), realpath, strlen(realpath) + 1)) {
-+              if (!(opline->result.u.EA.type & EXT_TYPE_UNUSED)) {
-+                      ALLOC_INIT_ZVAL(APC_EX_T(opline->result.u.var).var.ptr);
-+                      ZVAL_TRUE(APC_EX_T(opline->result.u.var).var.ptr);
-+              }
-+              if (inc_filename == &tmp_inc_filename) {
-+                      zval_dtor(&tmp_inc_filename);
-+              }
-+              if (freeop1) {
-+                      zval_dtor(freeop1);
-+              }
-+              execute_data->opline++;
-+              return 0;
-+      }
++    if (semop(semid, &op, 1) < 0) {
++        if (errno != EINTR) {
++            apc_eprint("apc_sem_lock: semop(%d) failed:", semid);
++        }
++    }
++}
 +
-+      if (inc_filename == &tmp_inc_filename) {
-+              zval_dtor(&tmp_inc_filename);
-+      }
++int apc_sem_nonblocking_lock(int semid) 
++{
++    struct sembuf op;
 +
-+      if(APCG(reserved_offset) != -1) {
-+              /* Insanity alert: look into apc_compile.c for why a void** is cast to a apc_opflags_t* */
-+              flags = (apc_opflags_t*) & (execute_data->op_array->reserved[APCG(reserved_offset)]);
-+      }
++    op.sem_num = 0;
++    op.sem_op  = -1;
++    op.sem_flg = UNDO | IPC_NOWAIT;
 +
-+#ifdef ZEND_ENGINE_2
-+      if(flags && flags->deep_copy == 1) {
-+              /* Since the op array is a local copy, we can cheat our way through the file inclusion by temporarily 
-+               * changing the op to a plain require/include, calling its handler and finally restoring the opcode.
-+               */
-+              Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE;
-+              ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-+              Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE;
-+#else 
-+      if(0) {
-+              /* do nothing, have nothing, be nothing */
-+#endif
-+      } else {
-+              ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
-+      }
++    if (semop(semid, &op, 1) < 0) {
++      if (errno == EAGAIN) {
++        return 0;  /* Lock is already held */
++      } else if (errno != EINTR) {
++        apc_eprint("apc_sem_lock: semop(%d) failed:", semid);
++      }
++    }
 +
-+      return ret;
++    return 1;  /* Lock obtained */
 +}
 +
-+void apc_zend_init(TSRMLS_D)
++void apc_sem_unlock(int semid)
 +{
-+    zend_extension dummy_ext;
-+#ifdef ZEND_ENGINE_2
-+    APCG(reserved_offset) = zend_get_resource_handle(&dummy_ext); 
-+    assert(APCG(reserved_offset) == dummy_ext.resource_number);
-+    assert(APCG(reserved_offset) != -1);
-+    assert(sizeof(apc_opflags_t) <= sizeof(void*));
-+#endif
-+      if (!APCG(include_once)) {
-+              /* If we're not overriding the INCLUDE_OR_EVAL handler, then just skip this malarkey */
-+              return;
-+      }
-+
-+      memcpy(apc_opcode_handlers, zend_opcode_handlers, sizeof(apc_opcode_handlers));
++    struct sembuf op;
 +
-+      /* 5.0 exposes zend_opcode_handlers differently than 5.1 and later */
-+#ifdef ZEND_ENGINE_2_1
-+      apc_original_opcode_handlers = zend_opcode_handlers;
-+      zend_opcode_handlers = apc_opcode_handlers;
-+#else
-+      apc_original_opcode_handlers = apc_opcode_handlers;
-+#endif
++    op.sem_num = 0;
++    op.sem_op  = 1;
++    op.sem_flg = UNDO;
 +
-+      APC_REPLACE_OPCODE(ZEND_INCLUDE_OR_EVAL);
++    if (semop(semid, &op, 1) < 0) {
++        if (errno != EINTR) {
++            apc_eprint("apc_sem_unlock: semop(%d) failed:", semid);
++        }
++    }
 +}
 +
-+void apc_zend_shutdown(TSRMLS_D)
++void apc_sem_wait_for_zero(int semid)
 +{
-+      if (!APCG(include_once)) {
-+              /* Nothing changed, nothing to restore */
-+              return;
-+      }
++    struct sembuf op;
 +
-+#ifdef ZEND_ENGINE_2_1
-+      zend_opcode_handlers = apc_original_opcode_handlers;
-+#else
-+      memcpy(zend_opcode_handlers, apc_original_opcode_handlers, sizeof(apc_opcode_handlers));
-+#endif
++    op.sem_num = 0;
++    op.sem_op  = 0;
++    op.sem_flg = UNDO;
++
++    if (semop(semid, &op, 1) < 0) {
++        if (errno != EINTR) {
++            apc_eprint("apc_sem_waitforzero: semop(%d) failed:", semid);
++        }
++    }
 +}
 +
-+#else /* Opcode Overrides unavailable */
++int apc_sem_get_value(int semid)
++{
++    union semun arg;
++    unsigned short val[1];
 +
-+void apc_zend_init(TSRMLS_D) { }
-+void apc_zend_shutdown(TSRMLS_D) { }
++    arg.array = val;
++    if (semctl(semid, 0, GETALL, arg) < 0) {
++        apc_eprint("apc_sem_getvalue: semctl(%d,...) failed:", semid);
++    }
++    return val[0];
++}
 +
-+#endif /* APC_OPCODE_OVERRIDE */
++#endif /* APC_SEM_LOCKS */
 +
 +/*
 + * Local variables:
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/apc_zend.h php-5.2.5/ext/apc/apc_zend.h
---- php-5.2.5-orig/ext/apc/apc_zend.h  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/apc_zend.h       2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,53 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_sem.h php-5.3.1/ext/apc/apc_sem.h
+--- php-5.3.1.orig/ext/apc/apc_sem.h   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_sem.h        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,52 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -10661,21 +10802,20 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_zend.h php-5.2.5/ext/apc/apc_zend.h
 +
 + */
 +
-+/* $Id: apc_zend.h,v 3.8 2006/09/01 21:59:16 pollita Exp $ */
-+
-+#ifndef APC_ZEND_H
-+#define APC_ZEND_H
-+
-+/* Utilities for interfacing with the zend engine */
++/* $Id: apc_sem.h 268620 2008-11-09 02:30:49Z shire $ */
 +
-+#include "apc.h"
-+#include "apc_php.h"
++#ifndef APC_SEM_H
++#define APC_SEM_H
 +
-+extern void* apc_php_malloc(size_t n);
-+extern void apc_php_free(void* p);
++/* Wrapper functions for SysV sempahores */
 +
-+extern void apc_zend_init(TSRMLS_D);
-+extern void apc_zend_shutdown(TSRMLS_D);
++extern int apc_sem_create(const char* pathname, int proj, int initval);
++extern void apc_sem_destroy(int semid);
++extern void apc_sem_lock(int semid);
++extern int apc_sem_nonblocking_lock(int semid); 
++extern void apc_sem_unlock(int semid);
++extern void apc_sem_wait_for_zero(int semid);
++extern int apc_sem_get_value(int semid);
 +
 +#endif
 +
@@ -10684,18 +10824,18 @@ diff -ubrN php-5.2.5-orig/ext/apc/apc_zend.h php-5.2.5/ext/apc/apc_zend.h
 + * tab-width: 4
 + * c-basic-offset: 4
 + * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
 + * vim<600: expandtab sw=4 ts=4 sts=4
 + */
-diff -ubrN php-5.2.5-orig/ext/apc/arch/atomic.h php-5.2.5/ext/apc/arch/atomic.h
---- php-5.2.5-orig/ext/apc/arch/atomic.h       1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/arch/atomic.h    2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,38 @@
+diff -Naur php-5.3.1.orig/ext/apc/apc_shm.c php-5.3.1/ext/apc/apc_shm.c
+--- php-5.3.1.orig/ext/apc/apc_shm.c   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_shm.c        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,124 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -10705,39 +10845,125 @@ diff -ubrN php-5.2.5-orig/ext/apc/arch/atomic.h php-5.2.5/ext/apc/arch/atomic.h
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Brian Shire <shire@php.net>                                 |
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          Rasmus Lerdorf <rasmus@php.net>                             |
 +  +----------------------------------------------------------------------+
 +
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
++
++   All other licensing and usage conditions are those of the PHP Group.
++
 + */
 +
-+/* $Id: atomic.h,v 1.1 2006/09/29 07:13:01 shire Exp $ */
++/* $Id: apc_shm.c 273457 2009-01-13 15:16:42Z gopalv $ */
++
++#include "apc_shm.h"
++#include "apc.h"
++#ifdef PHP_WIN32
++/* shm functions are available in TSRM */
++#include <tsrm/tsrm_win32.h>
++#define key_t long
++#else
++#include <sys/ipc.h>
++#include <sys/shm.h>
++#include <sys/stat.h>
++#endif
++
++#ifndef SHM_R
++# define SHM_R 0444 /* read permission */
++#endif
++#ifndef SHM_A
++# define SHM_A 0222 /* write permission */
++#endif
 +
-+#ifndef APC_ARCH_ATOMIC_H
++int apc_shm_create(const char* pathname, int proj, size_t size)
++{
++    int shmid;  /* shared memory id */
++    int oflag;  /* permissions on shm */
++    key_t key;  /* shm key returned by ftok */
 +
-+#define APC_ARCH_ATOMIC_H
++    key = IPC_PRIVATE;
++#ifndef PHP_WIN32
++    /* no ftok yet for win32 */
++    if (pathname != NULL) {
++        if ((key = ftok(pathname, proj)) < 0) {
++            apc_eprint("apc_shm_create: ftok failed:");
++        }
++    }
++#endif
 +
-+#if defined __x86_64__
-+#include "x86_64/atomic.h"
++    oflag = IPC_CREAT | SHM_R | SHM_A;
++    if ((shmid = shmget(key, size, oflag)) < 0) {
++        apc_eprint("apc_shm_create: shmget(%d, %d, %d) failed: %s. It is possible that the chosen SHM segment size is higher than the operation system allows. Linux has usually a default limit of 32MB per segment.", key, size, oflag, strerror(errno));
++    }
 +
-+#elif defined __i386__
-+#include "i386/atomic.h"
++    return shmid;
++}
 +
-+#else
-+#error "Unknown or Unsupported Architecture.  If you would like futex suupport for your architecture, please file a request at http://pecl.php.net/bugs/report.php?package=APC"
++void apc_shm_destroy(int shmid)
++{
++    /* we expect this call to fail often, so we do not check */
++    shmctl(shmid, IPC_RMID, 0);
++}
++
++apc_segment_t apc_shm_attach(int shmid)
++{
++    apc_segment_t segment; /* shm segment */
++
++    if ((long)(segment.shmaddr = shmat(shmid, 0, 0)) == -1) {
++        apc_eprint("apc_shm_attach: shmat failed:");
++    }
++
++#ifdef APC_MEMPROTECT
++    
++    if ((long)(segment.roaddr = shmat(shmid, 0, SHM_RDONLY)) == -1) {
++        segment.roaddr = NULL;
++    }
 +
 +#endif
 +
++    /*
++     * We set the shmid for removal immediately after attaching to it. The
++     * segment won't disappear until all processes have detached from it.
++     */
++    apc_shm_destroy(shmid);
++    return segment;
++}
++
++void apc_shm_detach(apc_segment_t* segment)
++{
++    if (shmdt(segment->shmaddr) < 0) {
++        apc_eprint("apc_shm_detach: shmdt failed:");
++    }
 +
++#ifdef APC_MEMPROTECT
++    if (segment->roaddr && shmdt(segment->roaddr) < 0) {
++        apc_eprint("apc_shm_detach: shmdt failed:");
++    }
 +#endif
-diff -ubrN php-5.2.5-orig/ext/apc/arch/i386/atomic.h php-5.2.5/ext/apc/arch/i386/atomic.h
---- php-5.2.5-orig/ext/apc/arch/i386/atomic.h  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/arch/i386/atomic.h       2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,79 @@
++}
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_shm.h php-5.3.1/ext/apc/apc_shm.h
+--- php-5.3.1.orig/ext/apc/apc_shm.h   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_shm.h        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,56 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -10747,80 +10973,57 @@ diff -ubrN php-5.2.5-orig/ext/apc/arch/i386/atomic.h php-5.2.5/ext/apc/arch/i386
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Brian Shire <shire@php.net>                                 |
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
 +  +----------------------------------------------------------------------+
 +
-+ */
-+
-+/* $Id: atomic.h,v 1.1 2006/09/29 07:13:01 shire Exp $ */
-+
-+
-+#include <sys/syscall.h>
-+#include <sys/time.h>
-+#include <linux/futex.h>
-+
-+/* int sys_futex (void *futex, int op, int val, const struct timespec *timeout); */
-+static inline long int apc_sys_futex(void *futex, int op, int val, const struct timespec *timeout) {
-+
-+  long int ret;
-+
-+  /* i386 system calls are performed with nt 80h operation.
-+   *  the argument order is a, b, c, d, S, D  
-+   */ 
-+  asm volatile ("int $0x80" 
-+       : "=a" (ret)
-+       : "0" (SYS_futex), 
-+         "b" (futex), 
-+         "c" (op), 
-+         "d" (val),
-+         "S" (timeout)
-+       : "memory"
-+      );
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
 +
-+  return ret;
++   All other licensing and usage conditions are those of the PHP Group.
 +
-+
++ */
 +
++/* $Id: apc_shm.h 273456 2009-01-13 14:43:58Z gopalv $ */
 +
-+static inline int apc_cmpxchg(volatile int *ptr, int old, int new) {
++#ifndef APC_SHM_H
++#define APC_SHM_H
 +
-+    int prev;
++#include <sys/types.h>
++#ifdef PHP_WIN32
++#include <time.h>
++#endif
 +
-+    asm volatile ("LOCK cmpxchgl %1, %2"
-+                   : "=a" (prev)
-+                   : "r" (new), 
-+                     "m" (*(ptr)), 
-+                     "0"(old)
-+                   : "memory", "cc"
-+                 );
++#include "apc_sma.h"
 +
-+    return prev;
-+}
++/* Wrapper functions for unix shared memory */
 +
-+static inline int apc_xchg(volatile int *ptr, int new) {
++extern int apc_shm_create(const char* name, int proj, size_t size);
++extern void apc_shm_destroy(int shmid);
++extern apc_segment_t apc_shm_attach(int shmid);
++extern void apc_shm_detach(apc_segment_t* segment);
 +
-+  int ret;
-+  
-+  asm volatile ("LOCK xchgl %[new], %[ptr]"
-+                : "=a" (ret)
-+                : [new] "0" (new), 
-+                  [ptr] "m" (*(ptr))
-+                : "memory"
-+               );
-+
-+  return ret;
-+  
-+}
++#endif
 +
-diff -ubrN php-5.2.5-orig/ext/apc/arch/x86_64/atomic.h php-5.2.5/ext/apc/arch/x86_64/atomic.h
---- php-5.2.5-orig/ext/apc/arch/x86_64/atomic.h        1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/arch/x86_64/atomic.h     2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,80 @@
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_signal.c php-5.3.1/ext/apc/apc_signal.c
+--- php-5.3.1.orig/ext/apc/apc_signal.c        1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_signal.c     1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,195 @@
 +/*
 +  +----------------------------------------------------------------------+
 +  | APC                                                                  |
 +  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
++  | Copyright (c) 2006-2008 The PHP Group                                |
 +  +----------------------------------------------------------------------+
 +  | This source file is subject to version 3.01 of the PHP license,      |
 +  | that is bundled with this package in the file LICENSE, and is        |
@@ -10830,1259 +11033,3048 @@ diff -ubrN php-5.2.5-orig/ext/apc/arch/x86_64/atomic.h php-5.2.5/ext/apc/arch/x8
 +  | obtain it through the world-wide-web, please send a note to          |
 +  | license@php.net so we can mail you a copy immediately.               |
 +  +----------------------------------------------------------------------+
-+  | Authors: Brian Shire <shire@php.net>                                 |
++  | Authors: Lucas Nealan <lucas@php.net>                                |
 +  +----------------------------------------------------------------------+
 +
-+ */
-+
-+/* $Id: atomic.h,v 1.1 2006/09/29 07:13:01 shire Exp $ */
-+
++   This software was contributed to PHP by Facebook Inc. in 2007.
 +
-+#include <sys/syscall.h>
-+#include <sys/time.h>
-+#include <linux/futex.h>
++   Future revisions and derivatives of this source code must acknowledge
++   Facebook Inc. as the original contributor of this module by leaving
++   this note intact in the source code.
 +
-+/* int sys_futex (void *futex, int op, int val, const struct timespec *timeout); */
-+static inline long int apc_sys_futex(void *futex, int op, int val, const struct timespec *timeout) {
++   All other licensing and usage conditions are those of the PHP Group.
++ */
 +
-+  long int ret;
++ /* $Id: apc_signal.c 268255 2008-11-04 05:42:11Z rasmus $ */
 +
-+  /* x86_64 system calls are performed with the faster SYSCALL operation.
-+   *  the argument order is D, S, d, c, b, a rather than
-+   *  a, b, c, d, S, D as on the i386 int 80h call. 
-+  */ 
-+  asm volatile ("syscall" 
-+       : "=a" (ret)
-+       : "0" (SYS_futex), 
-+         "D" (futex), 
-+         "S" (op), 
-+         "d" (val),
-+         "c" (timeout)
-+       : "r11", "rcx", "memory"
-+      );
++ /* Allows apc to install signal handlers and maintain signalling
++    to already registered handlers. Registers all signals that
++    coredump by default and unmaps the shared memory segment
++    before the coredump. Note: PHP module init is called before 
++    signals are set by Apache and thus apc_set_signals should
++    be called in request init (RINIT)
++  */
 +
-+  return ret;
++#include "apc.h"
 +
-+} 
++#if HAVE_SIGACTION
++#include <signal.h>
++#include "apc_globals.h"
++#include "apc_sma.h"
++#include "apc_signal.h"
 +
++static apc_signal_info_t apc_signal_info = {0};
 +
-+static inline int apc_cmpxchg(volatile int *ptr, int old, int new) {
++static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*));
++static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context);
++static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context);
 +
-+    int prev;
++/* {{{ apc_core_unmap 
++ *  Coredump signal handler, unmaps shm and calls previously installed handlers 
++ */
++static void apc_core_unmap(int signo, siginfo_t *siginfo, void *context) 
++{
++    apc_sma_cleanup();
++    apc_rehandle_signal(signo, siginfo, context);
 +
-+    asm volatile ("LOCK cmpxchgl %1, %2"
-+                   : "=a" (prev)
-+                   : "r" (new), 
-+                     "m" (*(ptr)), 
-+                     "0"(old)
-+                   : "memory", "cc"
-+                 );
++#if !defined(WIN32) && !defined(NETWARE)
++    kill(getpid(), signo);
++#else
++    raise(signo);
++#endif
++} /* }}} */
 +
-+    return prev;
-+}
++/* {{{ apc_rehandle_signal
++ *  Call the previously registered handler for a signal
++ */
++static void apc_rehandle_signal(int signo, siginfo_t *siginfo, void *context)
++{
++    int i;
++    apc_signal_entry_t p_sig = {0};
 +
-+static inline int apc_xchg(volatile int *ptr, int new) {
++    for (i=0;  (i < apc_signal_info.installed && p_sig.signo != signo);  i++) {
++        p_sig = *apc_signal_info.prev[i];
++        if (p_sig.signo == signo) {
++            if (p_sig.siginfo) {
++                (*(void (*)(int, siginfo_t*, void*))p_sig.handler)(signo, siginfo, context);
++            } else {
++                (*(void (*)(int))p_sig.handler)(signo);
++            }
++        }
++    }
 +
-+    int ret;
-+  
-+    asm volatile ("LOCK xchgl %[new], %[ptr]"
-+                  : "=a" (ret)
-+                  : [new] "0" (new), 
-+                    [ptr] "m" (*(ptr))
-+                  : "memory"
-+                 );
++} /* }}} */
 +
-+    return ret;
-+    
-+}
++/* {{{ apc_register_signal
++ *  Set a handler for a previously installed signal and save so we can 
++ *  callback when handled 
++ */
++static int apc_register_signal(int signo, void (*handler)(int, siginfo_t*, void*))
++{
++    struct sigaction sa = {{0}};
++    apc_signal_entry_t p_sig = {0};
 +
-diff -ubrN php-5.2.5-orig/ext/apc/CHANGELOG php-5.2.5/ext/apc/CHANGELOG
---- php-5.2.5-orig/ext/apc/CHANGELOG   1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/CHANGELOG        2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,211 @@
-+3.0.16: 2007-12-26
-+- Fix for longstanding cache-full crash (Christian Seiler)
-+  http://news.php.net/php.pecl.dev/4951 for the details
-+- Added optional shm unmap on a fatal signal feature (Lucas Nealan)
-+- Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab)
-+- Minor cleanups (Lucas Nealan)
-+- Added configure option to enable apc_cache_info('filehits') (Shire)
++    if (sigaction(signo, NULL, &sa) == 0) {
++        if ((void*)sa.sa_handler == (void*)handler) {
++            return SUCCESS;
++        }
 +
-+3.0.15: 2007-10-18
-+- Eliminate a per-request time() syscall (Rasmus)
-+- Added rfc1867 prefix, name, and freq ini options (Shire)
-+- Allow deletion of individual user cache entries via apc.php (Sara)
-+- Fix overzealous cleanup during RSHUTDOWN (Gopal)
-+- Fix memory alignment and locking issues (Gopal) 
-+- Make apc_compile insert/replace entries (Shire)
-+- Make mixed inheritance recompile & cache afresh  (Gopal)
-+- Make nostat mode search include_path for canonicalization (Gopal)
-+- ZTS & other compile fixes (Gopal, Edin, Shire)
-+  
-+3.0.14: 2007-03-21
-+- Build fix (Shire)
-+- Don't hook the upload hook if APC is disabled (Rasmus)
-+- Local shadow cache support (Gopal)
-+- Avoid uneccessary loops over op_arrays for "known" auto-globals (Gopal)
-+- Fix apc_add() to overwrite timed out user entries (Rasmus)
-+- Fix double inclusion of files with conditional classes in php4 (Gopal)
-+- Allocator fixes to reduce fragmentation (Gopal)
++        if (sa.sa_handler != SIG_ERR && sa.sa_handler != SIG_DFL && sa.sa_handler != SIG_IGN) {
++            p_sig.signo = signo;
++            p_sig.siginfo = ((sa.sa_flags & SA_SIGINFO) == SA_SIGINFO);
++            p_sig.handler = (void *)sa.sa_handler;
 +
-+3.0.13: 2007-02-24
-+- File upload progress (Rasmus)
-+- Pthread mutex and spin locks (Shire)
-+- Recursive zval support for apc_fetch/_store (Shire, Gopal)
-+- apc.stat_ctime flag for ctime checks (Rasmus)
-+- Multiple key fetches with apc_fetch (Shire)
-+- Canary checks for shm memory deallocation (Gopal)
-+- Add hooks for external optimizer (Shire)
-+- Obsolete and remove apc optimizer (Gopal)
-+- APC info changes - cache insert rate, hit and miss rates (Shire)
-+- Fix apc_load_constants (Gopal)
-+- Rewrite dump opcode code to use vld (Gopal)
-+- Use apc_[ewn]print functions for error reporting (Shire) 
-+- Auto global fixes and refactoring (Gopal, Shire)
-+- Fix memory leaks in object serialization (Ilia)
-+- Memory cleanup code for destructor order (Gopal)
-+- Win32 build fixes (Ilia, Wez)
-+- ZTS and Php 4 build fixes (Bjori)
-+- Add apc_add() function (Rasmus)
-+- Add optional limited flag to apc_sma_info() (Rasmus)
++            apc_signal_info.prev = (apc_signal_entry_t **)apc_erealloc(apc_signal_info.prev, (apc_signal_info.installed+1)*sizeof(apc_signal_entry_t *));
++            apc_signal_info.prev[apc_signal_info.installed] = (apc_signal_entry_t *)apc_emalloc(sizeof(apc_signal_entry_t));
++            *apc_signal_info.prev[apc_signal_info.installed++] = p_sig;
++        } else {
++            /* inherit flags and mask if already set */
++            sigemptyset(&sa.sa_mask);
++            sa.sa_flags = 0;
++            sa.sa_flags |= SA_SIGINFO; /* we'll use a siginfo handler */
++#if defined(SA_ONESHOT)
++            sa.sa_flags = SA_ONESHOT;
++#elif defined(SA_RESETHAND)
++            sa.sa_flags = SA_RESETHAND;
++#endif
++        }
++        sa.sa_handler = (void*)handler;
 +
-+3.0.12p2: 2006-09-05
-+- Package version up
++        if (sigaction(signo, &sa, NULL) < 0) {
++            apc_wprint("Error installing apc signal handler for %d", signo);
++        }
 +
-+3.0,12p1: 2006-09-05
-+- PHP4 build fixes
++        return SUCCESS;
++    }
++    return FAILURE;
++} /* }}} */
 +
-+3.0.12: 2006-09-05
-+- PHP 5.2 compatibility (Gopal)
-+- TSRM fixes (Gopal)
-+- Add extra flags to op_array->reserved to improve op array 
-+  processing code (Gopal)
-+- Fix crashes in optimizer and cli mode (Ilia)
-+- Optimizer fixes for PHP5 (Ilia, Gopal)
-+- Allow multiple inclusions of a file with a dynamic class (Gopal)
-+- Php 4 function table and properties fixes (Gopal)
-+- Fix memory leaks in apc_cache_info (Gopal)
++/* {{{ apc_set_signals
++ *  Install our signal handlers */
++void apc_set_signals(TSRMLS_D) 
++{
++    if (APCG(coredump_unmap) && apc_signal_info.installed == 0) {
++        /* ISO C standard signals that coredump */
++        apc_register_signal(SIGSEGV, apc_core_unmap);
++        apc_register_signal(SIGABRT, apc_core_unmap);
++        apc_register_signal(SIGFPE, apc_core_unmap);
++        apc_register_signal(SIGILL, apc_core_unmap);
++        /* extended signals that coredump */
++#ifdef SIGBUS
++        apc_register_signal(SIGBUS, apc_core_unmap);
++#endif
++#ifdef SIGABORT
++        apc_register_signal(SIGABORT, apc_core_unmap);
++#endif
++#ifdef SIGEMT
++        apc_register_signal(SIGEMT, apc_core_unmap);
++#endif
++#ifdef SIGIOT
++        apc_register_signal(SIGIOT, apc_core_unmap);
++#endif
++#ifdef SIGQUIT
++        apc_register_signal(SIGQUIT, apc_core_unmap);
++#endif
++#ifdef SIGSYS
++        apc_register_signal(SIGSYS, apc_core_unmap);
++#endif
++#ifdef SIGTRAP
++        apc_register_signal(SIGTRAP, apc_core_unmap);
++#endif
++#ifdef SIGXCPU
++        apc_register_signal(SIGXCPU, apc_core_unmap);
++#endif
++#ifdef SIGXFSZ
++        apc_register_signal(SIGXFSZ, apc_core_unmap);
++#endif
++    }
++} /* }}} */
 +
-+3.0.11: 2006-08-16
-+- Made --enable-apc-mmap the default compile option (for real this time)
-+- Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
-+  only fetch header information to make it useful when you have tens of
-+  thousands of entries.  (Brian Shire)
-+- 64-bit fixes (George)
-+- Don't mix Full Path and Inode keys (George)
-+- Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
-+  require_once() and include_once() statements. (Sara)
-+- Add a non-blocking write_lock for cache inserts.  This is a better approach
-+  to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
-+- A bit of work on the optimizer.  (Sara)
-+- Various memory issues resolved. (Gopal)
++/* {{{ apc_set_signals
++ *  cleanup signals for shutdown */
++void apc_shutdown_signals() 
++{
++    int i=0;
++    if (apc_signal_info.installed > 0) {
++        for (i=0;  (i < apc_signal_info.installed);  i++) {
++            apc_efree(apc_signal_info.prev[i]);
++        }
++        apc_efree(apc_signal_info.prev);
++        apc_signal_info.installed = 0; /* just in case */
++    }
++}
 +
-+3.0.10: 2006-03-11
-+- Add apc.stat ini flag which defaults to 1.  If set to 0, the main script and any fullpath
-+  includes will not be stat'ed for any changes.  You will have to restart the server if you
-+  change anything.  This mode increases performance quite a bit, especially if you have a
-+  lot of includes.
++#endif  /* HAVE_SIGACTION */
 +
-+- Get rid of the lock safety net hack I added in 3.0.9.  It seems to cause more problems
-+  than it solves.  I'll need to revisit locking and signal handling at some point soon.
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_signal.h php-5.3.1/ext/apc/apc_signal.h
+--- php-5.3.1.orig/ext/apc/apc_signal.h        1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_signal.h     1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,51 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Lucas Nealan <lucas@php.net>                                |
++  +----------------------------------------------------------------------+
 +
-+3.0.9: 2006-03-04
-+- Eliminate rand() call when slam_defense is not set (Rasmus)
-+- Fix for __isset problem (Gopal)
-+- Rewrite allocator from a "best fit" to a "next fit" algorithm (Rasmus)
-+- Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
-+- Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
-+- Add cache busy flag which is set when an expunge is underway (Rasmus)
-+- Add automatic serialization of objects in apc_store() (Marcus)
-+- 64-bit .ini flag fix (Rasmus)
-+- Static members fix (Gopal)
-+- sma_cleanup() mem leak fix (Rasmus)
-+- Fix for http://pecl.php.net/bugs/5311 (Rasmus)
-+- Fix autoglobals JIT bug (Gopal)
-+- Fix instance bug (Gopal)
-+- Add a lock cleanup safety net to request shutdown (Rasmus)
-+- Fix apc.slam_defense edge-case bug (Rasmus)
-+- User entry memory usage tracking support (Ilia)
-+- Allow keys used in apc_store/apc_fetch/apc_delete to be binary safe and prevent conflicts between keys that are found at the start of other keys. (Ilia)
++ */
 +
-+3.0.8: 2005-08-24
-+Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
-+Cache corruption fix in cache-full cleanup code (Gopal)
++/* $Id: apc_signal.h 268255 2008-11-04 05:42:11Z rasmus $ */
 +
-+3.0.7: 2005-08-16
-+- Fix to apc.php to show final segment in frag chart. (Ilia)
-+- A couple of win32 fixes. (Frank)
-+- Add apc.enable_cli ini directive. (Rasmus)
-+- Add test cases. (Marcus)
-+- Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
-+- Simplify user cache handling by removing the user_cache_stack (Rasmus)
-+- Fix apc_fetch() memory corruption (Andrei,Rasmus)
-+- Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)
++#ifndef APC_SIGNAL_H
++#define APC_SIGNAL_H
 +
-+3.0.6: 2005-07-30
-+- Added apc.php to package.xml file.
-+- Track per-entry memory usage. (Val)
-+- Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
-+- fcntl locking robustness fixes. (Rasmus)
-+- Shared read-locks where possible. (Rasmus)
-+- Added file_update_protection configuration parameter. (Rasmus)
-+- Windows ZTS fixes (Frank)
++#include "apc.h"
++#include "apc_php.h"
 +
-+3.0.5: 2005-07-27
-+- Make it easier for sapis that only populate file_handle->filename to use APC. (Rasmus)
-+- Support extensions such as bcompiler that need to hook into compile_file. (Val)
-+- Ralf Becker's apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
-+- Segfault in cache cleanup code (Ilia, Rasmus)
++typedef struct apc_signal_entry_t {
++    int signo;          /* signal number */
++    int siginfo;        /* siginfo style handler calling */
++    void* handler;      /* signal handler */
++} apc_signal_entry_t;
 +
-+3.0.4: 2005-07-18
-+- Add win32 support (Edin )
-+- Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches (Rasmus)
-+- A couple of other minor fixes
++typedef struct apc_signal_info_t {
++    int installed;                  /* How many signals we've installed handles for */
++    apc_signal_entry_t **prev;      /* Previous signal handlers */
++} apc_signal_info_t;
 +
-+3.0.3: 2005-07-05
-+- Fix compile problem against PHP 5.0.x
++void apc_set_signals(TSRMLS_D);
++void apc_shutdown_signals();
 +
-+3.0.2: 2005-07-05
-+- Better shm error message
++#endif
 +
-+3.0.1: 2005-07-05
-+- PHP4 build fix
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_sma.c php-5.3.1/ext/apc/apc_sma.c
+--- php-5.3.1.orig/ext/apc/apc_sma.c   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_sma.c        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,738 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          Rasmus Lerdorf <rasmus@php.net>                             |
++  +----------------------------------------------------------------------+
 +
-+3.0: 2005-06-23
-+- PHP 5.1 support (Arun, Gopal, Rasmus)
-+- Major Inheritance bug fix (Arun, Gopal)
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
 +
-+2.0: 2003-02-10
-+- ground-up rewrite sharing none of the original source code (djc)
++   All other licensing and usage conditions are those of the PHP Group.
 +
-+1.0.10:
-+- merge mmap / shm code to be in one file, module supports both modes now [mpb 2001-05-15]
-+- added apc.mode config parameter [mpb 2001-05-15] NOTE: You'll have to add
-+  this parameter to your php.ini file to activate apc shm or mmap caching
-+- generic source cleanup (missing includes, PATH_MAX usage etc) [mpb
-+  2001-05-15]
-+- fixed: realpath return result checking in generate_key [mpb 2001-05-15]
-+- updated: gui updated (extras/apc_gui-1.0.2.tar.gz)
-+- experminental 'fast' cache-retrieval [djc 2001-05-20]
-+- fixed regex support [gws 2001-05-16]
-+- enhanced reader-writer lock support [rg 2001-05-07]
++ */
 +
-+1.0.9:
-+- fixed (?) memory alignment bug on 64 bit archiecures 
-+- added many cache visibiliy functions 
-+- added opional fcntl locks under shm version 
-+- numerous bug fixes 
++/* $Id: apc_sma.c 284580 2009-07-22 06:05:31Z kalle $ */
 +
-+1.0.8:
-+- added ability to detect and decompile compiled files placed as 'source'
-+  [gws,dw 2001-01-30]
-+- fixed apc_rstat bug [gws 2001-01-29]
-+- added hack to support included urls [gws 2001-01-30]
-+- fixed apc_cache_index [mb 2001-01-31]
-+- added multiple regex support [gs 2001-02-03]
-+- added apc_cache_info [mb,gs 2001-02-03]
++#include "apc_sma.h"
++#include "apc.h"
++#include "apc_globals.h"
++#include "apc_lock.h"
++#include "apc_shm.h"
++#include "apc_cache.h"
 +
-+1.0.7:
-+- partially fixed for Solaris [gws 2001-01-29]
-+- fixed mtime support for relative includes [gws 2001-01-29]
-+- code cleanup [yg,ta,gws 2001-01-29]
++#include <limits.h>
++#include "apc_mmap.h"
 +
-+1.0.6:
-+- support for mtime in mmap [yg,gws 2001-01-27]
-+- fixed indexed-array initialization bug [djc,gws 2001-01-27]
++#ifdef HAVE_VALGRIND_MEMCHECK_H
++#include <valgrind/memcheck.h>
++#endif
 +
-+1.0.5:
-+- support for relative include paths [djc,gws 2001-01-19]
-+- class member array support fixed [djc 2001-01-18]
-+- added apc_cache_index [gws 2001-01-18]
++enum { DEFAULT_NUMSEG=1, DEFAULT_SEGSIZE=30*1024*1024 };
 +
-+1.0.4:
-+- support for class hierarchies greater than two levels deep [djc 2001-01-17]
++static int sma_initialized = 0;     /* true if the sma has been initialized */
++static uint sma_numseg;     /* number of shm segments to allow */
++static size_t sma_segsize;          /* size of each shm segment */
++static apc_segment_t* sma_segments; /* array of shm segments */
++static int sma_lastseg = 0;         /* index of MRU segment */
 +
-+1.0.3:
-+- fixed support for class inheritance [djc 2001-01-16]
++typedef struct sma_header_t sma_header_t;
++struct sma_header_t {
++    apc_lck_t sma_lock;     /* segment lock, MUST BE ALIGNED for futex locks */
++    size_t segsize;         /* size of entire segment */
++    size_t avail;           /* bytes available (not necessarily contiguous) */
++#if ALLOC_DISTRIBUTION
++    size_t adist[30];
++#endif
++};
 +
-+1.0.2:
-+- support for inherited classes [gws 2001-01-15]
-+- support for intialization of class variables and objects [gws 2001-01-13]
++#define SMA_HDR(i)  ((sma_header_t*)((sma_segments[i]).shmaddr))
++#define SMA_ADDR(i) ((char*)(SMA_HDR(i)))
++#define SMA_RO(i)   ((char*)(sma_segments[i]).roaddr)
++#define SMA_LCK(i)  ((SMA_HDR(i))->sma_lock)
 +
-+1.0.1:
-+- added optional file modification time check [djc 2001-01-12]
-diff -ubrN php-5.2.5-orig/ext/apc/config.m4 php-5.2.5/ext/apc/config.m4
---- php-5.2.5-orig/ext/apc/config.m4   1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/config.m4        2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,238 @@
-+dnl
-+dnl $Id: config.m4,v 3.30 2007/12/26 22:31:20 rasmus Exp $
-+dnl
 +
-+AC_MSG_CHECKING(whether apc needs to get compiler flags from apxs)
-+AC_ARG_WITH(apxs,
-+[  --with-apxs[=FILE]      Get compiler flags from apxs -q.  Provide the
-+                          pathname to the Apache apxs tool; defaults to "apxs".],[
-+  if test "$withval" != "no"; then
-+    if test "$withval" = "yes"; then
-+      APXS=apxs
-+      $APXS -q CFLAGS >/dev/null 2>&1
-+      if test "$?" != "0" && test -x /usr/sbin/apxs; then #SUSE 6.x
-+        APXS=/usr/sbin/apxs
-+      elif test -x /usr/bin/apxs2;  then
-+        APXS=/usr/bin/apxs2
-+      elif test -x /usr/sbin/apxs2; then
-+        APXS=/usr/sbin/apxs2
-+      fi
-+    else
-+      PHP_EXPAND_PATH($withval, APXS)
-+    fi
-+
-+    $APXS -q CFLAGS >/dev/null 2>&1
-+    if test "$?" != "0"; then
-+      AC_MSG_RESULT()
-+      AC_MSG_RESULT()
-+      AC_MSG_RESULT([Sorry, I was not able to successfully run APXS.  Possible reasons:])
-+      AC_MSG_RESULT()
-+      AC_MSG_RESULT([1.  Perl is not installed;])
-+      AC_MSG_RESULT([2.  Apache was not compiled with DSO support (--enable-module=so);])
-+      AC_MSG_RESULT([3.  'apxs' is not in your path.  Try to use --with-apxs=/path/to/apxs])
-+      AC_MSG_RESULT([The output of $APXS follows])
-+      $APXS -q CFLAGS
-+      AC_MSG_ERROR([Aborting])
-+    fi
-+
-+    APC_CFLAGS=`$APXS -q CFLAGS`
-+    AC_MSG_RESULT(yes)
-+  else
-+    AC_MSG_RESULT(no)
-+  fi
-+],[
-+  AC_MSG_RESULT(no)
-+])
++/* do not enable for threaded http servers */
++/* #define __APC_SMA_DEBUG__ 1 */
 +
-+PHP_ARG_ENABLE(apc, whether to enable APC support,
-+[  --enable-apc           Enable APC support])
++#ifdef __APC_SMA_DEBUG__
++/* global counter for identifying blocks
++ * Technically it is possible to do the same
++ * using offsets, but double allocations of the
++ * same offset can happen. */
++static volatile size_t block_id = 0;
++#endif
 +
-+AC_MSG_CHECKING(Checking whether we should enable cache request file info)
-+AC_ARG_ENABLE(apc-filehits,
-+[  --enable-apc-filehits   Enable per request file info about files used from the APC cache (ie: apc_cache_info('filehits')) ],
-+[
-+  PHP_APC_FILEHITS=$enableval
-+      AC_MSG_RESULT($enableval)
-+], 
-+[
-+  PHP_APC_FILEHITS=no
-+      AC_MSG_RESULT(no)
-+])
++#define APC_SMA_CANARIES 1
 +
++typedef struct block_t block_t;
++struct block_t {
++    size_t size;       /* size of this block */
++    size_t prev_size;  /* size of sequentially previous block, 0 if prev is allocated */
++    size_t fnext;      /* offset in segment of next free block */
++    size_t fprev;      /* offset in segment of prev free block */
++#ifdef APC_SMA_CANARIES
++    size_t canary;     /* canary to check for memory overwrites */
++#endif
++#ifdef __APC_SMA_DEBUG__
++    size_t id;         /* identifier for the memory block */
++#endif
++};
 +
++/* The macros BLOCKAT and OFFSET are used for convenience throughout this
++ * module. Both assume the presence of a variable shmaddr that points to the
++ * beginning of the shared memory segment in question. */
 +
-+AC_MSG_CHECKING(Checking whether we should use mmap)
-+AC_ARG_ENABLE(apc-mmap,
-+[  --disable-apc-mmap
-+                          Disable mmap support and use IPC shm instead],
-+[
-+  PHP_APC_MMAP=$enableval
-+  AC_MSG_RESULT($enableval)
-+], [
-+  PHP_APC_MMAP=yes
-+  AC_MSG_RESULT(yes)
-+])
++#define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
++#define OFFSET(block) ((size_t)(((char*)block) - (char*)shmaddr))
 +
-+AC_MSG_CHECKING(Checking whether we should use semaphore locking instead of fcntl)
-+AC_ARG_ENABLE(apc-sem,
-+[  --enable-apc-sem
-+                          Enable semaphore locks instead of fcntl],
-+[
-+  PHP_APC_SEM=$enableval
-+  AC_MSG_RESULT($enableval)
-+], [
-+  PHP_APC_SEM=no
-+  AC_MSG_RESULT(no)
-+])
++/* macros for getting the next or previous sequential block */
++#define NEXT_SBLOCK(block) ((block_t*)((char*)block + block->size))
++#define PREV_SBLOCK(block) (block->prev_size ? ((block_t*)((char*)block - block->prev_size)) : NULL)
 +
-+AC_MSG_CHECKING(Checking whether we should use futex locking)
-+AC_ARG_ENABLE(apc-futex,
-+[  --enable-apc-futex
-+                          Enable linux futex based locks  EXPERIMENTAL ],
-+[
-+  PHP_APC_FUTEX=$enableval
-+  AC_MSG_RESULT($enableval)
-+],
-+[
-+  PHP_APC_FUTEX=no
-+  AC_MSG_RESULT(no)
-+])
++/* Canary macros for setting, checking and resetting memory canaries */
++#ifdef APC_SMA_CANARIES
++    #define SET_CANARY(v) (v)->canary = 0x42424242
++    #define CHECK_CANARY(v) assert((v)->canary == 0x42424242)
++    #define RESET_CANARY(v) (v)->canary = -42
++#else
++    #define SET_CANARY(v) 
++    #define CHECK_CANARY(v)
++    #define RESET_CANARY(v)
++#endif
 +
-+if test "$PHP_APC_FUTEX" != "no"; then
-+      AC_CHECK_HEADER(linux/futex.h, , [ AC_MSG_ERROR([futex.h not found.  Please verify you that are running a 2.5 or older linux kernel and that futex support is enabled.]); ] )
-+fi
 +
-+AC_MSG_CHECKING(Checking whether we should use pthread mutex locking)
-+AC_ARG_ENABLE(apc-pthreadmutex,
-+[  --disable-apc-pthreadmutex
-+                          Disable pthread mutex locking ],
-+[
-+  PHP_APC_PTHREADMUTEX=no
-+  AC_MSG_RESULT(no)
-+],
-+[
-+  PHP_APC_PTHREADMUTEX=yes
-+  AC_MSG_RESULT(yes)
-+])
-+if test "$PHP_APC_PTHREADMUTEX" != "no"; then
-+      orig_LIBS="$LIBS"
-+      LIBS="$LIBS -lpthread"
-+      AC_TRY_RUN(
-+                      [
-+                              #include <sys/types.h>
-+                              #include <pthread.h>
-+                                main() {
-+                              pthread_mutex_t mutex;
-+                              pthread_mutexattr_t attr;       
++/* {{{ MINBLOCKSIZE */
++#define MINBLOCKSIZE (ALIGNWORD(1) + ALIGNWORD(sizeof(block_t)))
++/* }}} */
 +
-+                              if(pthread_mutexattr_init(&attr)) { 
-+                                      puts("Unable to initialize pthread attributes (pthread_mutexattr_init).");
-+                                      return -1; 
-+                              }
-+                              if(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) { 
-+                                      puts("Unable to set PTHREAD_PROCESS_SHARED (pthread_mutexattr_setpshared), your system may not support shared mutex's.");
-+                                      return -1; 
-+                              }       
-+                              if(pthread_mutex_init(&mutex, &attr)) { 
-+                                      puts("Unable to initialize the mutex (pthread_mutex_init).");
-+                                      return -1; 
-+                              }
-+                              if(pthread_mutexattr_destroy(&attr)) { 
-+                                      puts("Unable to destroy mutex attributes (pthread_mutexattr_destroy).");
-+                                      return -1; 
-+                              }
-+                              if(pthread_mutex_destroy(&mutex)) { 
-+                                      puts("Unable to destroy mutex (pthread_mutex_destroy).");
-+                                      return -1; 
-+                              }
-+
-+                              puts("pthread mutex's are supported!");
-+                              return 0;
-+                                }
-+                      ],
-+                      [ dnl -Success-
-+                              PHP_ADD_LIBRARY(pthread)
-+                      ],
-+                      [ dnl -Failure-
-+                              AC_MSG_WARN([It doesn't appear that pthread mutex's are supported on your system])
-+                      PHP_APC_PTHREADMUTEX=no
-+                      ],
-+                      [
-+                              PHP_ADD_LIBRARY(pthread)
-+                      ]
-+      )
-+      LIBS="$orig_LIBS"
-+fi
++#if 0
++/* {{{ sma_debug_state(apc_sma_segment_t *segment, int canary_check, int verbose)
++ *        useful for debuging state of memory blocks and free list, and sanity checking
++ */
++static void sma_debug_state(void* shmaddr, int canary_check, int verbose) {
++    sma_header_t *header = (sma_header_t*)shmaddr;
++    block_t *cur = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
++    block_t *prv = NULL;
++    size_t avail;
++
++    /* Verify free list */
++    if (verbose) apc_wprint("Free List: ");
++    while(1) {
++        if (verbose) apc_wprint(" 0x%x[%d] (s%d)", cur, OFFSET(cur), cur->size);
++        if (canary_check) CHECK_CANARY(cur);
++        if (!cur->fnext) break;
++        cur = BLOCKAT(cur->fnext);
++        avail += cur->size;
++        if (prv == cur) {
++            apc_wprint("Circular list detected!");
++            assert(0);
++        }
++        if (prv && cur->fprev != OFFSET(prv)) {
++            apc_wprint("Previous pointer does not point to previous!");
++            assert(0);
++        }
++        prv = cur;
++    }
++    assert(avail == header->avail);
 +
-+AC_MSG_CHECKING(Checking whether we should use spin locks)
-+AC_ARG_ENABLE(apc-spinlocks,
-+[  --enable-apc-spinlocks
-+                          Enable spin locks  EXPERIMENTAL ],
-+[
-+  PHP_APC_SPINLOCKS=$enableval
-+  AC_MSG_RESULT($enableval)
-+],
-+[
-+  PHP_APC_SPINLOCKS=no
-+  AC_MSG_RESULT(no)
-+])
++    /* Verify each block */
++    if (verbose) apc_wprint("Block List: ");
++    cur = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
++    while(1) {
++        if(!cur->fnext) {
++            if (verbose) apc_wprint(" 0x%x[%d] (s%d) (u)", cur, OFFSET(cur), cur->size);
++        } else {
++            if (verbose) apc_wprint(" 0x%x[%d] (s%d) (f)", cur, OFFSET(cur), cur->size);
++        }
++        if (canary_check) CHECK_CANARY(cur);
++        if (!cur->size && !cur->fnext) break;
++        if (!cur->size) {
++            cur = BLOCKAT(OFFSET(cur) + ALIGNWORD(sizeof(block_t)));
++        } else {
++            cur = NEXT_SBLOCK(cur);
++        }
++        if (prv == cur) {
++            apc_wprint("Circular list detected!");
++            assert(0);
++        }
++        prv = cur;
++    }
++}
++/* }}} */
++#endif
 +
-+if test "$PHP_APC" != "no"; then
-+  test "$PHP_APC_MMAP" != "no" && AC_DEFINE(APC_MMAP, 1, [ ])
-+  test "$PHP_APC_FILEHITS" != "no" && AC_DEFINE(APC_FILEHITS, 1, [ ])
++/* {{{ sma_allocate: tries to allocate at least size bytes in a segment */
++static size_t sma_allocate(sma_header_t* header, size_t size, size_t fragment, size_t *allocated)
++{
++    void* shmaddr;          /* header of shared memory segment */
++    block_t* prv;           /* block prior to working block */
++    block_t* cur;           /* working block in list */
++    block_t* prvnextfit;    /* block before next fit */
++    size_t realsize;        /* actual size of block needed, including header */
++    const size_t block_size = ALIGNWORD(sizeof(struct block_t));
 +
-+      if test "$PHP_APC_SEM" != "no"; then
-+              AC_DEFINE(APC_SEM_LOCKS, 1, [ ])
-+      elif test "$PHP_APC_FUTEX" != "no"; then
-+              AC_DEFINE(APC_FUTEX_LOCKS, 1, [ ])
-+      elif test "$PHP_APC_SPINLOCKS" != "no"; then
-+              AC_DEFINE(APC_SPIN_LOCKS, 1, [ ]) 
-+      elif test "$PHP_APC_PTHREADMUTEX" != "no"; then 
-+              AC_DEFINE(APC_PTHREADMUTEX_LOCKS, 1, [ ])
-+      fi
++    realsize = ALIGNWORD(size + block_size);
 +
-+  AC_CHECK_FUNCS(sigaction)
-+  AC_CACHE_CHECK(for union semun, php_cv_semun,
-+  [
-+    AC_TRY_COMPILE([
-+#include <sys/types.h>
-+#include <sys/ipc.h>
-+#include <sys/sem.h>
-+    ], [union semun x;], [
-+      php_cv_semun=yes
-+    ],[
-+      php_cv_semun=no
-+    ])
-+  ])
-+  if test "$php_cv_semun" = "yes"; then
-+    AC_DEFINE(HAVE_SEMUN, 1, [ ])
-+  else
-+    AC_DEFINE(HAVE_SEMUN, 0, [ ])
-+  fi
++    /*
++     * First, insure that the segment contains at least realsize free bytes,
++     * even if they are not contiguous.
++     */
++    shmaddr = header;
 +
-+  apc_sources="apc.c php_apc.c \
-+               apc_cache.c \
-+               apc_compile.c \
-+               apc_debug.c \
-+               apc_fcntl.c \
-+               apc_main.c \
-+               apc_mmap.c \
-+               apc_sem.c \
-+               apc_shm.c \
-+               apc_futex.c \
-+               apc_pthreadmutex.c \
-+               apc_spin.c \
-+               pgsql_s_lock.c \
-+               apc_sma.c \
-+               apc_stack.c \
-+               apc_zend.c \
-+               apc_rfc1867.c \
-+               apc_signal.c "
++    if (header->avail < realsize) {
++        return -1;
++    }
 +
-+  PHP_CHECK_LIBRARY(rt, shm_open, [PHP_ADD_LIBRARY(rt,,APC_SHARED_LIBADD)])
-+  PHP_NEW_EXTENSION(apc, $apc_sources, $ext_shared,, \\$(APC_CFLAGS))
-+  PHP_SUBST(APC_SHARED_LIBADD)
-+  PHP_SUBST(APC_CFLAGS)
-+  AC_DEFINE(HAVE_APC, 1, [ ])
-+fi
++    prvnextfit = 0;     /* initially null (no fit) */
++    prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
++    CHECK_CANARY(prv);
 +
-diff -ubrN php-5.2.5-orig/ext/apc/INSTALL php-5.2.5/ext/apc/INSTALL
---- php-5.2.5-orig/ext/apc/INSTALL     1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/INSTALL  2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,422 @@
-+Installation Instructions for APC
-+---------------------------------
++    while (prv->fnext != 0) {
++        cur = BLOCKAT(prv->fnext);
++#ifdef __APC_SMA_DEBUG__
++        CHECK_CANARY(cur);
++#endif
++        /* If it can fit realsize bytes in cur block, stop searching */
++        if (cur->size >= realsize) {
++            prvnextfit = prv;
++            break;
++        }
++        prv = cur;
++    }
 +
-+This version of APC should work on PHP 4.3.0 - 4.4.x and
-+5.1.0 - 5.2.x.  Yes, that means PHP 5.0.x is no longer 
-+supported.  Upgrade to PHP 5.1.x or 5.2.x and you will 
-+notice all sorts of performance increases.
++    if (prvnextfit == 0) {
++        return -1;
++    }
 +
-+CVS Instructions
-+----------------
-+Building from CVS can be done like this:
++    prv = prvnextfit;
++    cur = BLOCKAT(prv->fnext);
 +
-+  cvs -d :pserver:cvsread@cvs.php.net:/repository login
-+  Password: phpfi
-+  cvs -d :pserver:cvsread@cvs.php.net:/repository co pecl/apc
-+  cd pecl/apc
-+  phpize
-+  ./configure --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
-+  make
-+  make install
++    CHECK_CANARY(prv);
++    CHECK_CANARY(cur);
 +
-+Suggested Configuration (in your php.ini file)
-+----------------------------------------------
-+  extension=apc.so
-+  apc.enabled=1
-+  apc.shm_segments=1
-+  apc.shm_size=128
-+  apc.ttl=7200
-+  apc.user_ttl=7200
-+  apc.num_files_hint=1024
-+  apc.mmap_file_mask=/tmp/apc.XXXXXX
-+  apc.enable_cli=1
++    if (cur->size == realsize || (cur->size > realsize && cur->size < (realsize + (MINBLOCKSIZE + fragment)))) {
++        /* cur is big enough for realsize, but too small to split - unlink it */
++        *(allocated) = cur->size - block_size;
++        prv->fnext = cur->fnext;
++        BLOCKAT(cur->fnext)->fprev = OFFSET(prv);
++        NEXT_SBLOCK(cur)->prev_size = 0;  /* block is alloc'd */
++    } else {
++        /* nextfit is too big; split it into two smaller blocks */
++        block_t* nxt;      /* the new block (chopped part of cur) */
++        size_t oldsize;    /* size of cur before split */
 +
-+These are fully described at the bottom of this file.
++        oldsize = cur->size;
++        cur->size = realsize;
++        *(allocated) = cur->size - block_size;
++        nxt = NEXT_SBLOCK(cur);
++        nxt->prev_size = 0;                       /* block is alloc'd */
++        nxt->size = oldsize - realsize;           /* and fix the size */
++        NEXT_SBLOCK(nxt)->prev_size = nxt->size;  /* adjust size */
++        SET_CANARY(nxt);
 +
-+PHP 4 Optimization
-+------------------
-+If you are trying to get every little bit of speed out of PHP4+APC, you need
-+to tell APC where to find your httpd.h file and also add -DAPC_PHP4_STAT to
-+your CPPFLAGS.  (if you don't have httpd.h, install the apache_dev package 
-+for your OS) and do:
-+  export CPPFLAGS="-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for bash on Debian)
-+  setenv CPPFLAGS "-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for tsch on Debian)
-+and then re-run your configure script.
++        /* replace cur with next in free list */
++        nxt->fnext = cur->fnext;
++        nxt->fprev = cur->fprev;
++        BLOCKAT(nxt->fnext)->fprev = OFFSET(nxt);
++        BLOCKAT(nxt->fprev)->fnext = OFFSET(nxt);
++#ifdef __APC_SMA_DEBUG__
++        nxt->id = -1;
++#endif
++    }
 +
-+This optimization saves a stat syscall on the main script file.  In PHP5 this
-+optimization is automatic and doesn't need any special build flags.
++    cur->fnext = 0;
 +
-+The second thing you are going to want to do to save another syscall is to 
-+compile using the --with-apxs configure switch.  This should work for both
-+Apache1 and Apache2.  Point it directly at your apxs2 script for Apache2.
-+eg. --with-apxs=/usr/local/bin/apxs2
++    /* update the block header */
++    header->avail -= cur->size;
++#if ALLOC_DISTRIBUTION
++    header->adist[(int)(log(size)/log(2))]++;
++#endif
 +
-++---------------------+
-+| QUICK INSTALL (DSO) |
-++---------------------+
++    SET_CANARY(cur);
++#ifdef __APC_SMA_DEBUG__
++    cur->id = ++block_id;
++    fprintf(stderr, "allocate(realsize=%d,size=%d,id=%d)\n", (int)(size), (int)(cur->size), cur->id);
++#endif
 +
-+These instructions assume your PHP installation is located in /usr/local/php and you
-+want Apache optimizations (--with-apxs).
++    return OFFSET(cur) + block_size;
++}
++/* }}} */
 +
-+$ gunzip -c apc_x.y.tar.gz | tar xf -
-+$ cd apc_x.y
-+$ /usr/local/php/bin/phpize
-+$ ./configure --enable-apc --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
-+$ make
-+$ make install
++/* {{{ sma_deallocate: deallocates the block at the given offset */
++static size_t sma_deallocate(void* shmaddr, size_t offset)
++{
++    sma_header_t* header;   /* header of shared memory segment */
++    block_t* cur;       /* the new block to insert */
++    block_t* prv;       /* the block before cur */
++    block_t* nxt;       /* the block after cur */
++    size_t size;        /* size of deallocated block */
 +
-+You will probably need to run the final command (make install) as root.
++    offset -= ALIGNWORD(sizeof(struct block_t));
++    assert(offset >= 0);
 +
-+The above sequence of commands will install a .so file in your PHP
-+installation extension directory. The output of make install should display
-+that path to the screen.
++    /* find position of new block in free list */
++    cur = BLOCKAT(offset);
 +
-+Next you must edit your php.ini file, which is normally located in
-+/usr/local/php/lib/php.ini, and add the following line:
++    /* update the block header */
++    header = (sma_header_t*) shmaddr;
++    header->avail += cur->size;
++    size = cur->size;
 +
-+    extension="apc.so"
++    if (cur->prev_size != 0) {
++        /* remove prv from list */
++        prv = PREV_SBLOCK(cur);
++        BLOCKAT(prv->fnext)->fprev = prv->fprev;
++        BLOCKAT(prv->fprev)->fnext = prv->fnext;
++        /* cur and prv share an edge, combine them */
++        prv->size +=cur->size;
++        RESET_CANARY(cur);
++        cur = prv;
++    }
 +
-+Replace "/path/to/php/extensions" with whatever path was displayed when you
-+ran make install above.
++    nxt = NEXT_SBLOCK(cur);
++    if (nxt->fnext != 0) {
++        assert(NEXT_SBLOCK(NEXT_SBLOCK(cur))->prev_size == nxt->size);
++        /* cur and nxt shared an edge, combine them */
++        BLOCKAT(nxt->fnext)->fprev = nxt->fprev;
++        BLOCKAT(nxt->fprev)->fnext = nxt->fnext;
++        cur->size += nxt->size;
++#ifdef __APC_SMA_DEBUG__
++        CHECK_CANARY(nxt);
++        nxt->id = -1; /* assert this or set it ? */
++#endif
++        RESET_CANARY(nxt);
++    }
 +
-+Then restart your web server and consult the output of phpinfo(). If there is
-+an informational section for APC, the installation was successful.
++    NEXT_SBLOCK(cur)->prev_size = cur->size;
 +
-++------------------------+
-+| QUICK INSTALL (Static) |
-++------------------------+
++    /* insert new block after prv */
++    prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
++    cur->fnext = prv->fnext;
++    prv->fnext = OFFSET(cur);
++    cur->fprev = OFFSET(prv);
++    BLOCKAT(cur->fnext)->fprev = OFFSET(cur);
 +
-+APC will not successfully compile on all systems as a DSO. If you run into
-+problems using the DSO quick install, you can try to compile it statically
-+into PHP. (The DSO install is recommended, though.)
++    return size;
++}
++/* }}} */
 +
-+These instructions assume the current directory is the root of the PHP source
-+tree, and that you have already configured PHP by running its bundled
-+configure script.
++/* {{{ apc_sma_init */
 +
-+$ cd ext
-+$ gunzip -c apc_x.y.tar.gz | tar xf -
-+$ cd ..
-+$ ./buildconf
-+$ ./config.nice
-+$ make
-+$ make install
++void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask)
++{
++    uint i;
 +
-+Once this is complete, simply restart your web server. You do not need to
-+modify your php.ini file to enable APC.
++    if (sma_initialized) {
++        return;
++    }
++    sma_initialized = 1;
 +
-++-----------------+
-+| VERBOSE INSTALL |
-++-----------------+
++#if APC_MMAP
++    /*
++     * I don't think multiple anonymous mmaps makes any sense
++     * so force sma_numseg to 1 in this case
++     */
++    if(!mmap_file_mask || 
++       (mmap_file_mask && !strlen(mmap_file_mask)) ||
++       (mmap_file_mask && !strcmp(mmap_file_mask, "/dev/zero"))) {
++        sma_numseg = 1;
++    } else {
++        sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
++    }
++#else
++    sma_numseg = numseg > 0 ? numseg : DEFAULT_NUMSEG;
++#endif
 +
-+These instructions assume your PHP installation is located in /usr/local/php.
++    sma_segsize = segsize > 0 ? segsize : DEFAULT_SEGSIZE;
 +
-+1.  Unpack your distribution file.
++    sma_segments = (apc_segment_t*) apc_emalloc(sma_numseg*sizeof(apc_segment_t));
 +
-+    You will have downloaded a file named something like apc_x.y.tar.gz.
-+    Unzip this file with a command like
-+    
-+        gunzip apc_x.y.tar.gz
-+    
-+    Next you have to untar it with
-+    
-+        tar xvf apc_x.y.tar
++    for (i = 0; i < sma_numseg; i++) {
++        sma_header_t*   header;
++        block_t*    block;
++        void*       shmaddr;
 +
-+    This will create an apc_x.y directory. cd into this new directory:
++#if APC_MMAP
++        sma_segments[i] = apc_mmap(mmap_file_mask, sma_segsize);
++        if(sma_numseg != 1) memcpy(&mmap_file_mask[strlen(mmap_file_mask)-6], "XXXXXX", 6);
++#else
++        sma_segments[i] = apc_shm_attach(apc_shm_create(NULL, i, sma_segsize));
++#endif
++        
++        sma_segments[i].size = sma_segsize;
 +
-+        cd apc_x.y
++        shmaddr = sma_segments[i].shmaddr;
 +
-+2.  Run phpize.
++        header = (sma_header_t*) shmaddr;
++        apc_lck_create(NULL, 0, 1, header->sma_lock);
++        header->segsize = sma_segsize;
++        header->avail = sma_segsize - ALIGNWORD(sizeof(sma_header_t)) - ALIGNWORD(sizeof(block_t)) - ALIGNWORD(sizeof(block_t));
++#if ALLOC_DISTRIBUTION
++        {
++           int j;
++           for(j=0; j<30; j++) header->adist[j] = 0;
++        }
++#endif
++        block = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
++        block->size = 0;
++        block->fnext = ALIGNWORD(sizeof(sma_header_t)) + ALIGNWORD(sizeof(block_t));
++        block->fprev = 0;
++        block->prev_size = 0;
++        SET_CANARY(block);
++#ifdef __APC_SMA_DEBUG__
++        block->id = -1;
++#endif
++        block = BLOCKAT(block->fnext);
++        block->size = header->avail - ALIGNWORD(sizeof(block_t));
++        block->fnext = OFFSET(block) + block->size;
++        block->fprev = ALIGNWORD(sizeof(sma_header_t));
++        block->prev_size = 0;
++        SET_CANARY(block);
++#ifdef __APC_SMA_DEBUG__
++        block->id = -1;
++#endif
++        block = BLOCKAT(block->fnext);
++        block->size = 0;
++        block->fnext = 0;
++        block->fprev =  ALIGNWORD(sizeof(sma_header_t)) + ALIGNWORD(sizeof(block_t));
++        block->prev_size = header->avail - ALIGNWORD(sizeof(block_t));
++        SET_CANARY(block);
++#ifdef __APC_SMA_DEBUG__
++        block->id = -1;
++#endif
++    }
++}
++/* }}} */
 +
-+    phpize is a script that should have been installed with PHP, and is
-+    normally located in /usr/local/php/bin assuming you installed PHP in
-+    /usr/local/php. (If you do not have the phpize script, you must reinstall
-+    PHP and be sure not to disable PEAR.)
++/* {{{ apc_sma_cleanup */
++void apc_sma_cleanup()
++{
++    uint i;
 +
-+    Run the phpize command:
++    assert(sma_initialized);
++
++    for (i = 0; i < sma_numseg; i++) {
++        apc_lck_destroy(SMA_LCK(i));
++#if APC_MMAP
++        apc_unmap(&sma_segments[i]);
++#else
++        apc_shm_detach(&sma_segments[i]);
++#endif
++    }
++    sma_initialized = 0;
++    apc_efree(sma_segments);
++}
++/* }}} */
++
++/* {{{ apc_sma_malloc_ex */
++void* apc_sma_malloc_ex(size_t n, size_t fragment, size_t* allocated)
++{
++    size_t off;
++    uint i;
++
++    TSRMLS_FETCH();
++    assert(sma_initialized);
++    LOCK(SMA_LCK(sma_lastseg));
++
++    off = sma_allocate(SMA_HDR(sma_lastseg), n, fragment, allocated);
++
++    if(off == -1 && APCG(current_cache)) { 
++        /* retry failed allocation after we expunge */
++        UNLOCK(SMA_LCK(sma_lastseg));
++        APCG(current_cache)->expunge_cb(APCG(current_cache), n);
++        LOCK(SMA_LCK(sma_lastseg));
++        off = sma_allocate(SMA_HDR(sma_lastseg), n, fragment, allocated);
++    }
++
++    if (off != -1) {
++        void* p = (void *)(SMA_ADDR(sma_lastseg) + off);
++        UNLOCK(SMA_LCK(sma_lastseg));
++#ifdef VALGRIND_MALLOCLIKE_BLOCK
++        VALGRIND_MALLOCLIKE_BLOCK(p, n, 0, 0);
++#endif
++        return p;
++    }
 +    
-+        /usr/local/php/bin/phpize
++    UNLOCK(SMA_LCK(sma_lastseg));
 +
-+    Its output should resemble this:
++    for (i = 0; i < sma_numseg; i++) {
++        if (i == sma_lastseg) {
++            continue;
++        }
++        LOCK(SMA_LCK(i));
++        off = sma_allocate(SMA_HDR(i), n, fragment, allocated);
++        if(off == -1 && APCG(current_cache)) { 
++            /* retry failed allocation after we expunge */
++            UNLOCK(SMA_LCK(i));
++            APCG(current_cache)->expunge_cb(APCG(current_cache), n);
++            LOCK(SMA_LCK(i));
++            off = sma_allocate(SMA_HDR(i), n, fragment, allocated);
++        }
++        if (off != -1) {
++            void* p = (void *)(SMA_ADDR(i) + off);
++            UNLOCK(SMA_LCK(i));
++            sma_lastseg = i;
++#ifdef VALGRIND_MALLOCLIKE_BLOCK
++            VALGRIND_MALLOCLIKE_BLOCK(p, n, 0, 0);
++#endif
++            return p;
++        }
++        UNLOCK(SMA_LCK(i));
++    }
 +
-+        autoheader: `config.h.in' is created
-+        You should update your `aclocal.m4' by running aclocal.
-+        Configuring for:
-+          PHP Api Version:   20020918
-+          Zend Module Api No:   20020429
-+          Zend Extension Api No:   20021010
-+ 
-+    phpize should create a configure script in the current directory. If you
-+    get errors instead, you might be missing some required development tools,
-+    such as autoconf or libtool. You can try downloading the latest versions
-+    of those tools and running phpize again.
-+ 
-+3.  Run the configure script.
-+ 
-+    phpize creates a configure script. The only option you need to specify is
-+    the location of your php-config script:
++    return NULL;
++}
++/* }}} */
 +
-+        ./configure --enable-apc
++/* {{{ apc_sma_malloc */
++void* apc_sma_malloc(size_t n)
++{
++    size_t allocated;
++    void *p = apc_sma_malloc_ex(n, MINBLOCKSIZE, &allocated);
 +
-+    php-config should be located in the same directory as phpize.
++    return p;
++}
++/* }}} */
 +
-+    If you prefer to use mmap instead of the default IPC shared memory support,
-+    add --enable-apc-mmap to your configure line. 
++/* {{{ apc_sma_realloc */
++void* apc_sma_realloc(void *p, size_t n)
++{
++    apc_sma_free(p);
++    return apc_sma_malloc(n);
++}
++/* }}} */
 +
-+      If you prefer to use sysv IPC semaphores over the safer fcntl() locks, add
-+      --enable-sem to your configure line.  If you don't have a problem
-+      with your server segaulting, or any other unnatural accumulation of
-+      semaphores on your system, the semaphore based locking is slightly faster.
++/* {{{ apc_sma_strdup */
++char* apc_sma_strdup(const char* s)
++{
++    void* q;
++    int len;
 +
-+4.  Compile and install the files. Simply type: make install
++    if(!s) return NULL;
 +
-+    (You may need to be root in order to install)
++    len = strlen(s)+1;
++    q = apc_sma_malloc(len);
++    if(!q) return NULL;
++    memcpy(q, s, len);
++    return q;
++}
++/* }}} */
 +
-+    If you encounter errors from libtool or gcc during this step, please
-+    contact the project maintainer (dcowgill@php.net).
++/* {{{ apc_sma_free */
++void apc_sma_free(void* p)
++{
++    uint i;
++    size_t offset;
++    size_t d_size;
 +
-+5.  Edit your php.ini
++    if (p == NULL) {
++        return;
++    }
 +
-+    make install should have printed a line resembling the following:
++    assert(sma_initialized);
 +
-+        Installing shared extensions: /path/to/extension/
++    
++    for (i = 0; i < sma_numseg; i++) {
++        offset = (size_t)((char *)p - SMA_ADDR(i));
++        if (p >= (void*)SMA_ADDR(i) && offset < sma_segsize) {
++            LOCK(SMA_LCK(i));
++            d_size = sma_deallocate(SMA_HDR(i), offset);
++            UNLOCK(SMA_LCK(i));
++#ifdef VALGRIND_FREELIKE_BLOCK
++            VALGRIND_FREELIKE_BLOCK(p, 0);
++#endif
++            return;
++        }
++    }
 +
-+    Copy the path /path/to/extension/ and add the following line to your
-+    php.ini file (normally located in /usr/local/php/lib/php.ini):
++    apc_eprint("apc_sma_free: could not locate address %p", p);
++}
++/* }}} */
 +
-+        extension="apc.so"
++#ifdef APC_MEMPROTECT
++/* {{{ */
++void* apc_sma_protect(void *p)
++{
++    int i;
++    size_t offset;
 +
-+    If you don't have a php.ini file in that location, you can create it now.
++    if (p == NULL) {
++        return NULL;
++    }
 +
-+6.  Restart the web server and test the installation.
++    if(SMA_RO(sma_lastseg) == NULL) return p;
 +
-+    Restart your web server now (for apache, it's apachectl restart) and
-+    create a small test PHP file in your document root. The file should
-+    contain just the following line:
++    offset = (size_t)((char *)p - SMA_ADDR(sma_lastseg));
 +
-+        <?php phpinfo() ?>
++    if(p >= (void*)SMA_ADDR(sma_lastseg) && offset < sma_segsize) {
++        return SMA_RO(sma_lastseg) + offset;
++    }
 +
-+    Request that file in a web browser. If there is an entry for APC in the
-+    list of installed modules, the installation was successful.
++    for (i = 0; i < sma_numseg; i++) {
++        offset = (size_t)((char *)p - SMA_ADDR(i));
++        if (p >= (void*)SMA_ADDR(i) && offset < sma_segsize) {
++            return SMA_RO(i) + offset;
++        }
++    }
 +
-+    If APC is not listed, consult your web server error log. If it contains an
-+    error message saying that it can't load the APC extension, your system
-+    might not be able to load shared libraries created with PHP's build
-+    system. One alternative would be to compile APC statically into PHP. See
-+    the Quick Install (Static) instructions above.
++    return NULL;
++}
++/* }}} */
 +
-+    You should consult your error log anyway to see if APC generated any
-+    errors. On BSD-based platforms, it is typical for APC to be unable to
-+    allocate the default-sized shared memory segment. See below for hints on
-+    raising your system's shared memory limitations.
++/* {{{ */
++void* apc_sma_unprotect(void *p)
++{
++    int i;
++    size_t offset;
 +
-++-----------------+
-+| CONFIGURING APC |
-++-----------------+
++    if (p == NULL) {
++        return NULL;
++    }
 +
-+Although the default APC settings are fine for many installations, serious
-+users should consider tuning the following parameters:
++    if(SMA_RO(sma_lastseg) == NULL) return p;
 +
-+    OPTION                  DESCRIPTION
-+    ------------------      --------------------------------------------------
-+    apc.enabled             This can be set to 0 to disable APC. This is
-+                            primarily useful when APC is statically compiled
-+                            into PHP, since there is no other way to disable
-+                            it (when compiled as a DSO, the zend_extension
-+                            line can just be commented-out).
-+                            (Default: 1)
-+                            
-+    apc.shm_segments        The number of shared memory segments to allocate
-+                            for the compiler cache. If APC is running out of
-+                            shared memory but you have already set
-+                            apc.shm_size as high as your system allows, you
-+                            can try raising this value.  Setting this to a
-+                            value other than 1 has no effect in mmap mode
-+                            since mmap'ed shm segments don't have size limits.
-+                            (Default: 1)
-+                            
-+    apc.shm_size            The size of each shared memory segment in MB.
-+                            By default, some systems (including most BSD
-+                            variants) have very low limits on the size of a
-+                            shared memory segment.
-+                            (Default: 30)
-+                            
-+    apc.optimization        This option has been deprecated.
-+                            (Default: 0)
-+    
-+    apc.num_files_hint      A "hint" about the number of distinct source files
-+                            that will be included or requested on your web
-+                            server. Set to zero or omit if you're not sure;
-+                            this setting is mainly useful for sites that have
-+                            many thousands of source files.
-+                            (Default: 1000)
-+
-+    apc.user_entries_hint   Just like num_files_hint, a "hint" about the number
-+                            of distinct user cache variables to store. 
-+                            Set to zero or omit if you're not sure;
-+                            (Default: 4096)
++    offset = (size_t)((char *)p - SMA_RO(sma_lastseg));
 +
-+    apc.ttl                 The number of seconds a cache entry is allowed to
-+                            idle in a slot in case this cache entry slot is 
-+                            needed by another entry.  Leaving this at zero
-+                            means that your cache could potentially fill up
-+                            with stale entries while newer entries won't be
-+                            cached.  
-+                            (Default: 0)
++    if(p >= (void*)SMA_RO(sma_lastseg) && offset < sma_segsize) {
++        return SMA_ADDR(sma_lastseg) + offset;
++    }
 +
-+    apc.user_ttl            The number of seconds a user cache entry is allowed 
-+                            to idle in a slot in case this cache entry slot is 
-+                            needed by another entry.  Leaving this at zero
-+                            means that your cache could potentially fill up
-+                            with stale entries while newer entries won't be
-+                            cached.  
-+                            (Default: 0)
++    for (i = 0; i < sma_numseg; i++) {
++        offset = (size_t)((char *)p - SMA_RO(i));
++        if (p >= (void*)SMA_RO(i) && offset < sma_segsize) {
++            return SMA_ADDR(i) + offset;
++        }
++    }
 +
++    return NULL;
++}
++/* }}} */
++#else
++/* {{{ */
++void* apc_sma_protect(void *p) { return p; }
++void* apc_sma_unprotect(void *p) { return p; }
++/* }}} */
++#endif
 +
-+    apc.gc_ttl              The number of seconds that a cache entry may
-+                            remain on the garbage-collection list. This value
-+                            provides a failsafe in the event that a server
-+                            process dies while executing a cached source file;
-+                            if that source file is modified, the memory
-+                            allocated for the old version will not be
-+                            reclaimed until this TTL reached. Set to zero to
-+                            disable this feature.
-+                            (Default: 3600)
++/* {{{ apc_sma_info */
++apc_sma_info_t* apc_sma_info(zend_bool limited)
++{
++    apc_sma_info_t* info;
++    apc_sma_link_t** link;
++    uint i;
++    char* shmaddr;
++    block_t* prv;
 +
-+    apc.cache_by_default    On by default, but can be set to off and used in
-+                            conjunction with positive apc.filters so that files
-+                            are only cached if matched by a positive filter.
-+                            (Default: On)
++    if (!sma_initialized) {
++        return NULL;
++    }
 +
-+    apc.filters             A comma-separated list of POSIX extended regular
-+                            expressions. If any pattern matches the source
-+                            filename, the file will not be cached. Note that
-+                            the filename used for matching is the one passed
-+                            to include/require, not the absolute path.  If the
-+                            first character of the expression is a + then the
-+                            expression will be additive in the sense that any
-+                            files matched by the expression will be cached, and
-+                            if the first character is a - then anything matched
-+                            will not be cached.  The - case is the default, so
-+                            it can be left off.
-+                            (Default: "")
++    info = (apc_sma_info_t*) apc_emalloc(sizeof(apc_sma_info_t));
++    info->num_seg = sma_numseg;
++    info->seg_size = sma_segsize - (ALIGNWORD(sizeof(sma_header_t)) + ALIGNWORD(sizeof(block_t)) + ALIGNWORD(sizeof(block_t)));
 +
-+    apc.mmap_file_mask      If compiled with MMAP support by using --enable-mmap
-+                            this is the mktemp-style file_mask to pass to the
-+                            mmap module for determing whether your mmap'ed memory
-+                            region is going to be file-backed or shared memory
-+                            backed.  For straight file-backed mmap, set it to
-+                            something like /tmp/apc.XXXXXX (exactly 6 X's).
-+                            To use POSIX-style shm_open/mmap put a ".shm"
-+                            somewhere in your mask.  eg.  "/apc.shm.XXXXXX"
-+                            You can also set it to "/dev/zero" to use your 
-+                            kernel's /dev/zero interface to anonymous mmap'ed 
-+                            memory.  Leaving it undefined will force an 
-+                            anonymous mmap.
-+                            (Default: "")
++    info->list = apc_emalloc(info->num_seg * sizeof(apc_sma_link_t*));
++    for (i = 0; i < sma_numseg; i++) {
++        info->list[i] = NULL;
++    }
 +
-+    apc.slam_defense        ** DEPRECATED - Use apc.write_lock instead **
-+                            On very busy servers whenever you start the server or
-+                            modify files you can create a race of many processes
-+                            all trying to cache the same file at the same time.
-+                            This option sets the percentage of processes that will
-+                            skip trying to cache an uncached file.  Or think of it
-+                            as the probability of a single process to skip caching.
-+                            For example, setting this to 75 would mean that there is
-+                            a 75% chance that the process will not cache an uncached
-+                            file.  So the higher the setting the greater the defense
-+                            against cache slams.  Setting this to 0 disables this
-+                            feature.
-+                            (Default: 0)
++    if(limited) return info;
 +
-+    apc.file_update_protection
-+                            When you modify a file on a live web server you really
-+                            should do so in an atomic manner.  That is, write to a
-+                            temporary file and rename (mv) the file into its permanent
-+                            position when it is ready.  Many text editors, cp, tar and
-+                            other such programs don't do this.  This means that there
-+                            is a chance that a file is accessed (and cached) while it
-+                            is still being written to.  This file_update_protection
-+                            setting puts a delay on caching brand new files.  The
-+                            default is 2 seconds which means that if the modification
-+                            timestamp (mtime) on a file shows that it is less than 2
-+                            seconds old when it is accessed, it will not be cached.  
-+                            The unfortunate person who accessed this half-written file
-+                            will still see weirdness, but at least it won't persist.
-+                            If you are certain you always atomically update your files
-+                            by using something like rsync which does this correctly, you
-+                            can turn this protection off by setting it to 0.  If you
-+                            have a system that is flooded with io causing some update
-+                            procedure to take longer than 2 seconds, you may want to
-+                            increase this a bit.
-+                            (Default: 2)
++    /* For each segment */
++    for (i = 0; i < sma_numseg; i++) {
++        RDLOCK(SMA_LCK(i));
++        shmaddr = SMA_ADDR(i);
++        prv = BLOCKAT(ALIGNWORD(sizeof(sma_header_t)));
 +
-+    apc.enable_cli          Mostly for testing and debugging.  Setting this enables APC
-+                            for the CLI version of PHP.  Normally you wouldn't want to
-+                            create, populate and tear down the APC cache on every CLI
-+                            request, but for various test scenarios it is handy to be
-+                            able to enable APC for the CLI version of APC easily.
-+                            (Default: 0)
++        link = &info->list[i];
 +
-+    apc.max_file_size       Prevents large files from being cached.  
-+                            (Default: 1M)
++        /* For each block in this segment */
++        while (BLOCKAT(prv->fnext)->fnext != 0) {
++            block_t* cur = BLOCKAT(prv->fnext);
++#ifdef __APC_SMA_DEBUG__
++            CHECK_CANARY(cur);
++#endif
 +
-+    apc.stat                Whether to stat the main script file and the fullpath
-+                            includes.  If you turn this off you will need to restart
-+                            your server in order to update scripts.
-+                            (Default: 1)
++            *link = apc_emalloc(sizeof(apc_sma_link_t));
++            (*link)->size = cur->size;
++            (*link)->offset = prv->fnext;
++            (*link)->next = NULL;
++            link = &(*link)->next;
 +
-+    apc.write_lock          On busy servers when you first start up the server, or when
-+                            many files are modified, you can end up with all your processes
-+                            trying to compile and cache the same files.  With write_lock 
-+                            enabled, only one process at a time will try to compile an
-+                            uncached script while the other processes will run uncached
-+                            instead of sitting around waiting on a lock.
-+                            (Default: 1)
++            prv = cur;
 +
-+    apc.report_autofilter   Logs any scripts that were automatically excluded from being
-+                            cached due to early/late binding issues.
-+                            (Default: 0)
++#if ALLOC_DISTRIBUTION
++            sma_header_t* header = (sma_header_t*) segment->shmaddr;
++            memcpy(info->seginfo[i].adist, header->adist, sizeof(size_t) * 30);
++#endif
 +
-+    apc.rfc1867             RFC1867 File Upload Progress hook handler is only available
-+                            if you compiled APC against PHP 5.2.0 or later.  When enabled
-+                            any file uploads which includes a field called 
-+                            APC_UPLOAD_PROGRESS before the file field in an upload form
-+                            will cause APC to automatically create an upload_<key>
-+                            user cache entry where <key> is the value of the 
-+                            APC_UPLOAD_PROGRESS form entry.
++        }
++        UNLOCK(SMA_LCK(i));
++    }
 +
-+                            Note that the file upload tracking is not threadsafe at this
-+                            point, so new uploads that happen while a previous one is 
-+                            still going will disable the tracking for the previous.
-+                            (Default: 0)
++    return info;
++}
++/* }}} */
 +
-+    apc.rfc1867_prefix      Key prefix to use for the user cache entry generated by
-+                            rfc1867 upload progress functionality.  
-+                            (Default: "upload_")
++/* {{{ apc_sma_free_info */
++void apc_sma_free_info(apc_sma_info_t* info)
++{
++    int i;
 +
-+    apc.rfc1867_name        Specify the hidden form entry name that activates APC upload
-+                            progress and specifies the user cache key suffix.
-+                            (Default: "APC_UPLOAD_PROGRESS")
++    for (i = 0; i < info->num_seg; i++) {
++        apc_sma_link_t* p = info->list[i];
++        while (p) {
++            apc_sma_link_t* q = p;
++            p = p->next;
++            apc_efree(q);
++        }
++    }
++    apc_efree(info->list);
++    apc_efree(info);
++}
++/* }}} */
 +
-+    apc.rfc1867_freq        The frequency that updates should be made to the user cache
-+                            entry for upload progress.  This can take the form of a 
-+                            percentage of the total file size or a size in bytes 
-+                            optionally suffixed with 'k', 'm', or 'g' for kilobytes, 
-+                            megabytes, or gigabytes respectively (case insensitive).  
-+                            A setting of 0 updates as often as possible, which may cause 
-+                            slower uploads.
-+                            (Default: 0)
++/* {{{ apc_sma_get_avail_mem */
++size_t apc_sma_get_avail_mem()
++{
++    size_t avail_mem = 0;
++    uint i;
 +
-+    apc.localcache          This enables a lock-free local process shadow-cache which 
-+                            reduces lock contention when the cache is being written to.
-+                            (Default: 0)
-+                            
-+    apc.localcache.size     The size of the local process shadow-cache, should be set to 
-+                            a sufficently large value, approximately half of num_files_hint.
-+                            (Default: 512)
-+    
-+    apc.include_once_override 
-+                            Optimize include_once and require_once calls and avoid the 
-+                            expensive system calls used.
-+                            (Default: 0)
-diff -ubrN php-5.2.5-orig/ext/apc/LICENSE php-5.2.5/ext/apc/LICENSE
---- php-5.2.5-orig/ext/apc/LICENSE     1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/LICENSE  2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,68 @@
-+-------------------------------------------------------------------- 
-+                  The PHP License, version 3.01
-+Copyright (c) 1999 - 2006 The PHP Group. All rights reserved.
-+-------------------------------------------------------------------- 
++    for (i = 0; i < sma_numseg; i++) {
++        sma_header_t* header = SMA_HDR(i);
++        avail_mem += header->avail;
++    }
++    return avail_mem;
++}
++/* }}} */
 +
-+Redistribution and use in source and binary forms, with or without
-+modification, is permitted provided that the following conditions
-+are met:
++#if ALLOC_DISTRIBUTION
++size_t *apc_sma_get_alloc_distribution(void) {
++    sma_header_t* header = (sma_header_t*) segment->sma_shmaddr;
++    return header->adist;
++}
++#endif
 +
-+  1. Redistributions of source code must retain the above copyright
-+     notice, this list of conditions and the following disclaimer.
-+ 
-+  2. Redistributions in binary form must reproduce the above copyright
-+     notice, this list of conditions and the following disclaimer in
-+     the documentation and/or other materials provided with the
-+     distribution.
-+ 
-+  3. The name "PHP" must not be used to endorse or promote products
-+     derived from this software without prior written permission. For
-+     written permission, please contact group@php.net.
-+  
-+  4. Products derived from this software may not be called "PHP", nor
-+     may "PHP" appear in their name, without prior written permission
-+     from group@php.net.  You may indicate that your software works in
-+     conjunction with PHP by saying "Foo for PHP" instead of calling
-+     it "PHP Foo" or "phpfoo"
-+ 
-+  5. The PHP Group may publish revised and/or new versions of the
-+     license from time to time. Each version will be given a
-+     distinguishing version number.
-+     Once covered code has been published under a particular version
-+     of the license, you may always continue to use it under the terms
-+     of that version. You may also choose to use such covered code
-+     under the terms of any subsequent version of the license
-+     published by the PHP Group. No one other than the PHP Group has
-+     the right to modify the terms applicable to covered code created
-+     under this License.
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_sma.h php-5.3.1/ext/apc/apc_sma.h
+--- php-5.3.1.orig/ext/apc/apc_sma.h   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_sma.h        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,102 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  +----------------------------------------------------------------------+
 +
-+  6. Redistributions of any form whatsoever must retain the following
-+     acknowledgment:
-+     "This product includes PHP software, freely available from
-+     <http://www.php.net/software/>".
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
 +
-+THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND 
-+ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
-+PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE PHP
-+DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
-+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
-+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
-+OF THE POSSIBILITY OF SUCH DAMAGE.
++   All other licensing and usage conditions are those of the PHP Group.
 +
-+-------------------------------------------------------------------- 
++ */
 +
-+This software consists of voluntary contributions made by many
-+individuals on behalf of the PHP Group.
++/* $Id: apc_sma.h 277617 2009-03-23 02:16:24Z shire $ */
 +
-+The PHP Group can be contacted via Email at group@php.net.
++#ifndef APC_SMA_H
++#define APC_SMA_H
 +
-+For more information on the PHP Group and the PHP project, 
-+please see <http://www.php.net>.
++#define ALLOC_DISTRIBUTION 0
 +
-+PHP includes the Zend Engine, freely available at
-+<http://www.zend.com>.
-diff -ubrN php-5.2.5-orig/ext/apc/NOTICE php-5.2.5/ext/apc/NOTICE
---- php-5.2.5-orig/ext/apc/NOTICE      1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/NOTICE   2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,43 @@
-+This is the NOTICE file that holds acknowledgements and stuff.
++#include "apc.h"
 +
-+The Alternative PHP Cache (APC) is a free and open opcode cache for PHP.
-+This extension is being released under the PHP License for complete compliance
-+with PHP and to encourage wide-spread use.  It is our intention that this
-+project be kept open source and that all commercial spin-offs contribute their
-+modifications back into the public source-tree.
++/* Simple shared memory allocator */
 +
-+Creators:
-+    Daniel Cowgill
-+    George Schlossnagle
++typedef struct _apc_segment_t apc_segment_t;
 +
-+PHP5 support and major features by:
-+    Arun C. Murthy 
-+    Gopal Vijayaraghavan
-+    Rasmus Lerdorf
++struct _apc_segment_t {
++    size_t size;
++    void* shmaddr;
++#ifdef APC_MEMPROTECT
++    void* roaddr;
++#endif
++};
 +
-+This software was contributed to PHP by Community Connect Inc. in 2002
-+and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+Future revisions and derivatives of this source code must acknowledge
-+Community Connect Inc. as the original contributor of this module by
-+leaving this note intact in the source code.
++extern void apc_sma_init(int numseg, size_t segsize, char *mmap_file_mask);
++extern void apc_sma_cleanup();
++extern void* apc_sma_malloc(size_t size);
++extern void* apc_sma_malloc_ex(size_t size, size_t fragment, size_t* allocated);
++extern void* apc_sma_realloc(void* p, size_t size);
++extern char* apc_sma_strdup(const char *s);
++extern void apc_sma_free(void* p);
++#if ALLOC_DISTRIBUTION 
++extern size_t *apc_sma_get_alloc_distribution();
++#endif
 +
-+All other licensing and usage conditions are those of the PHP Group.
++extern void* apc_sma_protect(void *p);
++extern void* apc_sma_unprotect(void *p);
 +
-+We would like to thank Community Connect Inc. and Yahoo! Inc. for supporting 
-+this project and providing a challenging and stimulating environment in 
-+which exciting projects can happen.
++/* {{{ struct definition: apc_sma_link_t */
++typedef struct apc_sma_link_t apc_sma_link_t;
++struct apc_sma_link_t {
++    long size;               /* size of this free block */
++    long offset;             /* offset in segment of this block */
++    apc_sma_link_t* next;   /* link to next free block */
++};
++/* }}} */
 +
-+Contributors:
-+    Mike Bretz          bug fixes, GUI, and lots of work
-+    Ricardo Galli       changed read-write locks to prefer readers
-+    Yann Grossel        bug fixes
-+    Thies Arntzen       bug fixes
-+    Sara Golemon        optimizer work
++/* {{{ struct definition: apc_sma_info_t */
++typedef struct apc_sma_info_t apc_sma_info_t;
++struct apc_sma_info_t {
++    int num_seg;            /* number of shared memory segments */
++    size_t seg_size;           /* size of each shared memory segment */
++    apc_sma_link_t** list;  /* there is one list per segment */
++};
++/* }}} */
 +
-+Special Thanks:
-+    Florian Baumert     help debugging phplib problems
-+    Thomas Duffey       help debugging inheritance issues
-+    Vibol Hou           help debugging phplib problems
-+    Angel Li            diffs for ANSI comment compliance
-+    Christian Rishøj    help debugging phplib problems
-+    Sascha Schumann     memory error bug fix
-diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
---- php-5.2.5-orig/ext/apc/package.xml 1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/package.xml      2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,534 @@
-+<?xml version="1.0" encoding="UTF-8"?>
-+<package packagerversion="1.4.9" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
-+ <name>APC</name>
-+ <channel>pecl.php.net</channel>
-+ <summary>Alternative PHP Cache</summary>
-+ <description>APC is a free, open, and robust framework for caching and optimizing PHP intermediate code.</description>
-+ <lead>
-+  <name>Daniel Cowgill</name>
-+  <user>dcowgill</user>
-+  <email>dan@mail.communityconnect.com</email>
-+  <active>no</active>
-+ </lead>
-+ <lead>
-+  <name>George Schlossnagle</name>
-+  <user>gschlossnagle</user>
-+  <email>george@omniti.com</email>
-+  <active>no</active>
-+ </lead>
-+ <lead>
-+  <name>Rasmus Lerdorf</name>
-+  <user>rasmus</user>
-+  <email>rasmus@php.net</email>
-+  <active>yes</active>
-+ </lead>
-+ <lead>
-+  <name>Gopal Vijayaraghavan</name>
-+  <user>gopalv</user>
-+  <email>gopalv@php.net</email>
-+  <active>yes</active>
-+ </lead>
-+ <developer>
-+  <name>Edin Kadribasic</name>
-+  <user>edink</user>
-+  <email>edink@emini.dk</email>
-+  <active>yes</active>
-+ </developer>
-+ <developer>
-+  <name>Ilia Alshanetsky</name>
-+  <user>iliaa</user>
-+  <email>ilia@prohost.org</email>
-+  <active>yes</active>
-+ </developer>
-+ <developer>
-+  <name>Marcus Börger</name>
-+  <user>helly</user>
-+  <email>helly@php.net</email>
-+  <active>yes</active>
-+ </developer>
-+ <developer>
-+  <name>Sara Golemon</name>
-+  <user>pollita</user>
-+  <email>pollita@php.net</email>
-+  <active>yes</active>
-+ </developer>
-+ <developer>
-+  <name>Brian Shire</name>
-+  <user>shire</user>
-+  <email>shire@php.net</email>
-+  <active>yes</active>
-+ </developer>
-+ <date>2007-12-26</date>
-+ <time>14:51:32</time>
-+ <version>
-+  <release>3.0.16</release>
-+  <api>3.0.0</api>
-+ </version>
-+ <stability>
-+  <release>stable</release>
-+  <api>stable</api>
-+ </stability>
-+ <license uri="http://www.php.net/license">PHP License</license>
-+ <notes>* Fix for longstanding cache-full crash (Christian Seiler)
-+  http://news.php.net/php.pecl.dev/4951 for the details
-+* Added optional shm unmap on a fatal signal feature (Lucas Nealan)
-+* Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab)
-+* Minor cleanups (Lucas Nealan)
-+* Added configure option to enable apc_cache_info(&apos;filehits&apos;) (Shire)</notes>
-+ <contents>
-+  <dir name="/">
-+   <file md5sum="841596cff3b9bd83e79d01ccb591ff55" name="tests/apc_001.phpt" role="test" />
-+   <file md5sum="cc1dba4e429ff93dce1ca7dea01c2899" name="tests/apc_002.phpt" role="test" />
-+   <file md5sum="411fdc85b170ec696298d38f93132d6b" name="tests/apc_003.phpt" role="test" />
-+   <file md5sum="6ecba4154b6bd6f8703000f5198710cc" name="tests/skipif.inc" role="test" />
-+   <file md5sum="2a2e8b29dba8df697dbd81b306ccbe73" name="arch/i386/atomic.h" role="src" />
-+   <file md5sum="7f01c5cd3a1742c20d6d285f119596a6" name="arch/x86_64/atomic.h" role="src" />
-+   <file md5sum="26748a0d6567c5611408eb69fb25c671" name="arch/atomic.h" role="src" />
-+   <file md5sum="0714a0039d9ea63cfc26043a7d86f04c" name="CHANGELOG" role="doc" />
-+   <file md5sum="3b6ad608e37fb34b24afb90084b4770b" name="INSTALL" role="doc" />
-+   <file md5sum="694f49a7e1f276ba75a3dd2c5acd580d" name="LICENSE" role="doc" />
-+   <file md5sum="eea150699d3dffb2cdf7d243854189d7" name="NOTICE" role="doc" />
-+   <file md5sum="efa40416571fc54aa59912203c0391e6" name="TODO" role="doc" />
-+   <file md5sum="b7dd14328e218d3ecc97d85fb83d7ba7" name="TECHNOTES.txt" role="doc" />
-+   <file md5sum="c4384f370db6a6112d6c21268bc9a278" name="apc.c" role="src" />
-+   <file md5sum="09a525ff9a3850e6de42eee2adf07463" name="apc.dsp" role="src" />
-+   <file md5sum="109694ee417962096eb3e962d6bcce8a" name="apc.h" role="src" />
-+   <file md5sum="ee19b49ef26dbd491b846a19f9bc9e6a" name="apc_cache.c" role="src" />
-+   <file md5sum="e0a4f0c5a49a0beba10f2f831e1b63b6" name="apc_cache.h" role="src" />
-+   <file md5sum="7576310688084dd737f7c7bc11c75e22" name="apc_compile.c" role="src" />
-+   <file md5sum="a0eea1abcf4ec395ea9a195e98c2cc65" name="apc_compile.h" role="src" />
-+   <file md5sum="64bbe1f8cf18261255ef5874039e76e9" name="apc_debug.c" role="src" />
-+   <file md5sum="46d182a6122f3c29a1904f62af7cfb51" name="apc_debug.h" role="src" />
-+   <file md5sum="3dbdb44d0fc2d45ae15719b4fc5746cd" name="apc_fcntl.c" role="src" />
-+   <file md5sum="f4fc86769ce871d42ce0085fa7323d79" name="apc_fcntl.h" role="src" />
-+   <file md5sum="9dffe726c9b6cfdd640e07782a0f409b" name="apc_futex.c" role="src" />
-+   <file md5sum="ff999238a10bfb6b715e4e8f54ec8326" name="apc_futex.h" role="src" />
-+   <file md5sum="33d241202d41095bc1b6fdafc1063cb9" name="apc_globals.h" role="src" />
-+   <file md5sum="3e6f98c635b18902aab221f29d8b70ec" name="apc_lock.h" role="src" />
-+   <file md5sum="0667187c715fea98569b51a491fb445b" name="apc_main.c" role="src" />
-+   <file md5sum="2e8f99d31b4d088eb14859c6e137544a" name="apc_main.h" role="src" />
-+   <file md5sum="e9e447ef3994b85d064c9a49f7ed0917" name="apc_mmap.c" role="src" />
-+   <file md5sum="a22df1256e20fef8160bbf9529723b50" name="apc_php.h" role="src" />
-+   <file md5sum="c285337c2e0b852de9f79ac5015a3fa7" name="apc_pthreadmutex.c" role="src" />
-+   <file md5sum="e4e6943b0cfb31facd1148c2dbfc4c93" name="apc_pthreadmutex.h" role="src" />
-+   <file md5sum="ea3822772adb45e0046faef855c32aba" name="apc_sem.c" role="src" />
-+   <file md5sum="1a7fb689f8d5b01fad537b277c81d59f" name="apc_sem.h" role="src" />
-+   <file md5sum="632e60d387e5555f4aa03a8948f52ea7" name="apc_shm.c" role="src" />
-+   <file md5sum="6de8e94976f01b2f48ef97020a008774" name="apc_shm.h" role="src" />
-+   <file md5sum="25d3e2a3d1c2f9afa8e103492ca7e89e" name="apc_sma.c" role="src" />
-+   <file md5sum="fdc0aebc501f2e29389611fa61084da0" name="apc_sma.h" role="src" />
-+   <file md5sum="ecd6cc1d56d99dbb7364d40c975fca5e" name="apc_spin.c" role="src" />
-+   <file md5sum="c716852258453471a6927f95a617e30f" name="apc_spin.h" role="src" />
-+   <file md5sum="17cceda297a61a9185bcafd7d897fad4" name="apc_stack.c" role="src" />
-+   <file md5sum="db2f213a3e616313d7864222874197ea" name="apc_stack.h" role="src" />
-+   <file md5sum="8cccb8ecfa2d5a893537b2c1a8b6b718" name="apc_zend.c" role="src" />
-+   <file md5sum="2ee61624ec5d779d02746ba7254aed14" name="apc_zend.h" role="src" />
-+   <file md5sum="113d74a5e70119a63fb86815bf50d03b" name="apc_signal.c" role="src" />
-+   <file md5sum="af4c7d0595ce32346f7ee37707d7dada" name="apc_signal.h" role="src" />
-+   <file md5sum="5cbb3cbe6477799e7e5fd816eda69937" name="config.m4" role="src" />
-+   <file md5sum="b748744f64eb4fbe201cce84cc3d7e33" name="php_apc.c" role="src" />
-+   <file md5sum="8c092033ef0cd8a5d207acb4f6ecec11" name="php_apc.h" role="src" />
-+   <file md5sum="76fe025ee14897783cee848dc1a77fa6" name="pgsql_s_lock.c" role="src" />
-+   <file md5sum="b67725b96ecf0e6851eccce632bab289" name="pgsql_s_lock.h" role="src" />
-+   <file md5sum="298e1c6721b21635ef46094c6a175af5" name="apc_fcntl_win32.c" role="src" />
-+   <file md5sum="072c127617c90a92331372a3b99494d3" name="apc_rfc1867.c" role="src" />
-+   <file md5sum="41fb805e7a151dc6edfe78780b5102d0" name="apc.php" role="php" />
-+  </dir>
-+ </contents>
-+ <dependencies>
-+  <required>
-+   <php>
-+    <min>4.3.0</min>
-+    <exclude>5.0.0</exclude>
-+    <exclude>5.0.1</exclude>
-+    <exclude>5.0.2</exclude>
-+    <exclude>5.0.3</exclude>
-+    <exclude>5.0.4</exclude>
-+    <exclude>5.0.5</exclude>
-+   </php>
-+   <pearinstaller>
-+    <min>1.4.0</min>
-+   </pearinstaller>
-+  </required>
-+ </dependencies>
-+ <providesextension>apc</providesextension>
-+ <extsrcrelease>
-+  <configureoption default="yes" name="with-apxs" prompt="Use apxs to set compile flags (if using APC with Apache)?" />
-+ </extsrcrelease>
-+ <changelog>
-+  <release>
-+   <stability>
-+    <release>stable</release>
-+    <api>stable</api>
-+   </stability>
-+   <version>
-+    <release>2.0.0</release>
-+    <api>2.0.0</api>
-+   </version>
-+   <date>2003-07-01</date>
-+   <notes>Complete rework.</notes>
-+  </release>
-+  <release>
-+   <stability>
-+    <release>stable</release>
-+    <api>stable</api>
++extern apc_sma_info_t* apc_sma_info(zend_bool limited);
++extern void apc_sma_free_info(apc_sma_info_t* info);
++
++extern size_t apc_sma_get_avail_mem();
++extern void apc_sma_check_integrity();
++
++/* {{{ ALIGNWORD: pad up x, aligned to the system's word boundary */
++typedef union { void* p; int i; long l; double d; void (*f)(); } apc_word_t;
++#define ALIGNSIZE(x, size) ((size) * (1 + (((x)-1)/(size))))
++#define ALIGNWORD(x) ALIGNSIZE(x, sizeof(apc_word_t))
++/* }}} */
++
++#endif
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_spin.c php-5.3.1/ext/apc/apc_spin.c
+--- php-5.3.1.orig/ext/apc/apc_spin.c  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_spin.c       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,66 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2007-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Brian Shire <shire@php.net>                                 |
++  +----------------------------------------------------------------------+
++
++ */
++
++/* $Id: apc_spin.c 268255 2008-11-04 05:42:11Z rasmus $ */
++
++#include "apc_spin.h"
++
++#ifdef APC_SPIN_LOCKS
++
++slock_t *apc_slock_create(slock_t *lock)
++{
++   S_INIT_LOCK(lock);
++   return lock;
++}
++
++void apc_slock_destroy(slock_t *lock)
++{
++    return;
++}
++
++void apc_slock_lock(slock_t *lock)
++{
++    S_LOCK(lock);
++}
++
++void apc_slock_unlock(slock_t *lock)
++{
++    S_UNLOCK(lock);
++}
++
++zend_bool apc_slock_nonblocking_lock(slock_t *lock)
++{
++    /* Technically we aren't supposed to call this directly, but the original
++     *  code provides no method for absolute non-blocking locks, so we'll call into
++     *  the TAS (test and set) functionality directly 
++     */
++    return !(TAS(lock));  /* if TAS returns 0 we obtained the lock, otherwise we failed */
++}
++
++
++#endif
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_spin.h php-5.3.1/ext/apc/apc_spin.h
+--- php-5.3.1.orig/ext/apc/apc_spin.h  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_spin.h       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,49 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2007-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Brian Shire <shire@php.net>                                 |
++  +----------------------------------------------------------------------+
++
++ */
++
++/* $Id: apc_spin.h 268255 2008-11-04 05:42:11Z rasmus $ */
++
++#ifndef APC_SPIN_H
++#define APC_SPIN_H
++
++#include "apc.h"
++
++#ifdef APC_SPIN_LOCKS
++
++#include "pgsql_s_lock.h"
++
++slock_t *apc_slock_create(slock_t *lock);
++void apc_slock_destroy(slock_t *lock);
++void apc_slock_lock(slock_t *lock);
++zend_bool apc_slock_nonblocking_lock(slock_t *lock);
++void apc_slock_lock(slock_t *lock);
++void apc_slock_unlock(slock_t *lock);
++
++#endif
++
++#endif
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_stack.c php-5.3.1/ext/apc/apc_stack.c
+--- php-5.3.1.orig/ext/apc/apc_stack.c 1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_stack.c      1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,106 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  +----------------------------------------------------------------------+
++
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
++
++   All other licensing and usage conditions are those of the PHP Group.
++
++ */
++
++/* $Id: apc_stack.c 268255 2008-11-04 05:42:11Z rasmus $ */
++
++#include "apc_stack.h"
++#include "apc.h"
++
++struct apc_stack_t {
++    void** data;
++    int capacity;
++    int size;
++};
++
++apc_stack_t* apc_stack_create(int size_hint)
++{
++    apc_stack_t* stack = (apc_stack_t*) apc_emalloc(sizeof(apc_stack_t));
++
++    stack->capacity = (size_hint > 0) ? size_hint : 10;
++    stack->size = 0;
++    stack->data = (void**) apc_emalloc(sizeof(void*) * stack->capacity);
++
++    return stack;
++}
++
++void apc_stack_destroy(apc_stack_t* stack)
++{
++    if (stack != NULL) {
++        apc_efree(stack->data);
++        apc_efree(stack);
++    }
++}
++
++void apc_stack_clear(apc_stack_t* stack)
++{
++    assert(stack != NULL);
++    stack->size = 0;
++}
++
++void apc_stack_push(apc_stack_t* stack, void* item)
++{
++    assert(stack != NULL);
++    if (stack->size == stack->capacity) {
++        stack->capacity *= 2;
++        stack->data = apc_erealloc(stack->data, sizeof(void*)*stack->capacity);
++    }
++    stack->data[stack->size++] = item;
++}
++
++void* apc_stack_pop(apc_stack_t* stack)
++{
++    assert(stack != NULL && stack->size > 0);
++    return stack->data[--stack->size];
++}
++
++void* apc_stack_top(apc_stack_t* stack)
++{
++    assert(stack != NULL && stack->size > 0);
++    return stack->data[stack->size-1];
++}
++
++void* apc_stack_get(apc_stack_t* stack, int n)
++{
++    assert(stack != NULL && stack->size > n);
++    return stack->data[n];
++}
++
++int apc_stack_size(apc_stack_t* stack)
++{
++    assert(stack != NULL);
++    return stack->size;
++}
++
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_stack.h php-5.3.1/ext/apc/apc_stack.h
+--- php-5.3.1.orig/ext/apc/apc_stack.h 1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_stack.h      1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,58 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          George Schlossnagle <george@omniti.com>                     |
++  +----------------------------------------------------------------------+
++
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
++
++   All other licensing and usage conditions are those of the PHP Group.
++
++ */
++
++/* $Id: apc_stack.h 268255 2008-11-04 05:42:11Z rasmus $ */
++
++#ifndef APC_STACK_H
++#define APC_STACK_H
++
++/* Basic stack datatype */
++
++#define T apc_stack_t*
++typedef struct apc_stack_t apc_stack_t; /* opaque stack type */
++
++extern T apc_stack_create(int size_hint);
++extern void apc_stack_destroy(T stack);
++extern void apc_stack_clear(T stack);
++extern void apc_stack_push(T stack, void* item);
++extern void* apc_stack_pop(T stack);
++extern void* apc_stack_top(T stack);
++extern void* apc_stack_get(T stack, int n);
++extern int apc_stack_size(T stack);
++
++#undef T
++#endif
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_zend.c php-5.3.1/ext/apc/apc_zend.c
+--- php-5.3.1.orig/ext/apc/apc_zend.c  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_zend.c       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,213 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  +----------------------------------------------------------------------+
++
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
++
++   All other licensing and usage conditions are those of the PHP Group.
++
++ */
++
++/* $Id: apc_zend.c 276053 2009-02-18 08:59:00Z gopalv $ */
++
++#include "apc_zend.h"
++#include "apc_globals.h"
++
++/* true global */
++int apc_reserved_offset;
++
++void* apc_php_malloc(size_t n)
++{
++    return emalloc(n);
++}
++
++void apc_php_free(void* p)
++{
++    efree(p);
++}
++
++#ifdef APC_OPCODE_OVERRIDE
++
++static opcode_handler_t *apc_original_opcode_handlers;
++static opcode_handler_t apc_opcode_handlers[APC_OPCODE_HANDLER_COUNT];
++
++#define APC_EX_T(offset)                    (*(temp_variable *)((char*)execute_data->Ts + offset))
++
++static zval *apc_get_zval_ptr(znode *node, zval **freeval, zend_execute_data *execute_data TSRMLS_DC)
++{
++    *freeval = NULL;
++
++    switch (node->op_type) {
++        case IS_CONST:
++            return &(node->u.constant);
++        case IS_VAR:
++            return APC_EX_T(node->u.var).var.ptr;
++        case IS_TMP_VAR:
++            return (*freeval = &APC_EX_T(node->u.var).tmp_var);
++#ifdef ZEND_ENGINE_2_1
++        case IS_CV:
++        {
++            zval ***ret = &execute_data->CVs[node->u.var];
++
++            if (!*ret) {
++                zend_compiled_variable *cv = &EG(active_op_array)->vars[node->u.var];
++
++                if (zend_hash_quick_find(EG(active_symbol_table), cv->name, cv->name_len+1, cv->hash_value, (void**)ret)==FAILURE) {
++                    apc_nprint("Undefined variable: %s", cv->name);
++                    return &EG(uninitialized_zval);
++                }
++            }
++            return **ret;
++        }
++#endif
++        case IS_UNUSED:
++        default:
++            return NULL;
++    }
++}
++
++static int ZEND_FASTCALL apc_op_ZEND_INCLUDE_OR_EVAL(ZEND_OPCODE_HANDLER_ARGS)
++{
++    APC_ZEND_OPLINE
++    zval *freeop1 = NULL;
++    zval *inc_filename = NULL, tmp_inc_filename;
++    char realpath[MAXPATHLEN];
++    php_stream_wrapper *wrapper;
++    char *path_for_open;
++    int ret = 0;
++    apc_opflags_t* flags = NULL;
++
++    if (Z_LVAL(opline->op2.u.constant) != ZEND_INCLUDE_ONCE &&
++        Z_LVAL(opline->op2.u.constant) != ZEND_REQUIRE_ONCE) {
++        return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
++    }
++
++    inc_filename = apc_get_zval_ptr(&opline->op1, &freeop1, execute_data TSRMLS_CC);
++    if (Z_TYPE_P(inc_filename) != IS_STRING) {
++        tmp_inc_filename = *inc_filename;
++        zval_copy_ctor(&tmp_inc_filename);
++        convert_to_string(&tmp_inc_filename);
++        inc_filename = &tmp_inc_filename;
++    }
++
++    wrapper = php_stream_locate_url_wrapper(Z_STRVAL_P(inc_filename), &path_for_open, 0 TSRMLS_CC);
++
++    if (wrapper != &php_plain_files_wrapper ||
++        !(IS_ABSOLUTE_PATH(path_for_open, strlen(path_for_open)) ||
++          expand_filepath(path_for_open, realpath TSRMLS_CC))) {
++        /* Fallback to original handler */
++        if (inc_filename == &tmp_inc_filename) {
++            zval_dtor(&tmp_inc_filename);
++        }
++        return apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
++    }
++
++    if (zend_hash_exists(&EG(included_files), realpath, strlen(realpath) + 1)) {
++        if (!(opline->result.u.EA.type & EXT_TYPE_UNUSED)) {
++            ALLOC_INIT_ZVAL(APC_EX_T(opline->result.u.var).var.ptr);
++            ZVAL_TRUE(APC_EX_T(opline->result.u.var).var.ptr);
++        }
++        if (inc_filename == &tmp_inc_filename) {
++            zval_dtor(&tmp_inc_filename);
++        }
++        if (freeop1) {
++            zval_dtor(freeop1);
++        }
++        execute_data->opline++;
++        return 0;
++    }
++
++    if (inc_filename == &tmp_inc_filename) {
++        zval_dtor(&tmp_inc_filename);
++    }
++
++    if(apc_reserved_offset != -1) {
++        /* Insanity alert: look into apc_compile.c for why a void** is cast to a apc_opflags_t* */
++        flags = (apc_opflags_t*) & (execute_data->op_array->reserved[apc_reserved_offset]);
++    }
++
++    if(flags && flags->deep_copy == 1) {
++        /* Since the op array is a local copy, we can cheat our way through the file inclusion by temporarily 
++         * changing the op to a plain require/include, calling its handler and finally restoring the opcode.
++         */
++        Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE_ONCE) ? ZEND_INCLUDE : ZEND_REQUIRE;
++        ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
++        Z_LVAL(opline->op2.u.constant) = (Z_LVAL(opline->op2.u.constant) == ZEND_INCLUDE) ? ZEND_INCLUDE_ONCE : ZEND_REQUIRE_ONCE;
++    } else {
++        ret = apc_original_opcode_handlers[APC_OPCODE_HANDLER_DECODE(opline)](ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
++    }
++
++    return ret;
++}
++
++void apc_zend_init(TSRMLS_D)
++{
++    zend_extension dummy_ext;
++    apc_reserved_offset = zend_get_resource_handle(&dummy_ext); 
++    assert(apc_reserved_offset == dummy_ext.resource_number);
++    assert(apc_reserved_offset != -1);
++    assert(sizeof(apc_opflags_t) <= sizeof(void*));
++    if (!APCG(include_once)) {
++        /* If we're not overriding the INCLUDE_OR_EVAL handler, then just skip this malarkey */
++        return;
++    }
++
++    memcpy(apc_opcode_handlers, zend_opcode_handlers, sizeof(apc_opcode_handlers));
++
++    /* 5.0 exposes zend_opcode_handlers differently than 5.1 and later */
++#ifdef ZEND_ENGINE_2_1
++    apc_original_opcode_handlers = zend_opcode_handlers;
++    zend_opcode_handlers = apc_opcode_handlers;
++#else
++    apc_original_opcode_handlers = apc_opcode_handlers;
++#endif
++
++    APC_REPLACE_OPCODE(ZEND_INCLUDE_OR_EVAL);
++}
++
++void apc_zend_shutdown(TSRMLS_D)
++{
++    if (!APCG(include_once)) {
++        /* Nothing changed, nothing to restore */
++        return;
++    }
++
++#ifdef ZEND_ENGINE_2_1
++    zend_opcode_handlers = apc_original_opcode_handlers;
++#else
++    memcpy(zend_opcode_handlers, apc_original_opcode_handlers, sizeof(apc_opcode_handlers));
++#endif
++}
++
++#else /* Opcode Overrides unavailable */
++
++void apc_zend_init(TSRMLS_D) { }
++void apc_zend_shutdown(TSRMLS_D) { }
++
++#endif /* APC_OPCODE_OVERRIDE */
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/apc_zend.h php-5.3.1/ext/apc/apc_zend.h
+--- php-5.3.1.orig/ext/apc/apc_zend.h  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/apc_zend.h       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,169 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  +----------------------------------------------------------------------+
++
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
++
++   All other licensing and usage conditions are those of the PHP Group.
++
++ */
++
++/* $Id: apc_zend.h 286799 2009-08-04 11:27:29Z gopalv $ */
++
++#ifndef APC_ZEND_H
++#define APC_ZEND_H
++
++/* Utilities for interfacing with the zend engine */
++
++#include "apc.h"
++#include "apc_php.h"
++
++#ifndef Z_REFCOUNT_P
++#define Z_REFCOUNT_P(pz)              (pz)->refcount
++#define Z_REFCOUNT_PP(ppz)            Z_REFCOUNT_P(*(ppz))
++#endif
++
++#ifndef Z_SET_REFCOUNT_P
++#define Z_SET_REFCOUNT_P(pz, rc)      (pz)->refcount = rc
++#define Z_SET_REFCOUNT_PP(ppz, rc)    Z_SET_REFCOUNT_P(*(ppz), rc)
++#endif
++
++#ifndef Z_ADDREF_P
++#define Z_ADDREF_P(pz)                (pz)->refcount++
++#define Z_ADDREF_PP(ppz)              Z_ADDREF_P(*(ppz))
++#endif
++
++#ifndef Z_DELREF_P
++#define Z_DELREF_P(pz)                (pz)->refcount--
++#define Z_DELREF_PP(ppz)              Z_DELREF_P(*(ppz))
++#endif
++
++#ifndef Z_ISREF_P
++#define Z_ISREF_P(pz)                 (pz)->is_ref
++#define Z_ISREF_PP(ppz)               Z_ISREF_P(*(ppz))
++#endif
++
++#ifndef Z_SET_ISREF_P
++#define Z_SET_ISREF_P(pz)             (pz)->is_ref = 1
++#define Z_SET_ISREF_PP(ppz)           Z_SET_ISREF_P(*(ppz))
++#endif
++
++#ifndef Z_UNSET_ISREF_P
++#define Z_UNSET_ISREF_P(pz)           (pz)->is_ref = 0
++#define Z_UNSET_ISREF_PP(ppz)         Z_UNSET_ISREF_P(*(ppz))
++#endif
++
++#ifndef Z_SET_ISREF_TO_P
++#define Z_SET_ISREF_TO_P(pz, isref)   (pz)->is_ref = isref
++#define Z_SET_ISREF_TO_PP(ppz, isref) Z_SET_ISREF_TO_P(*(ppz), isref)
++#endif
++
++
++extern void* apc_php_malloc(size_t n);
++extern void apc_php_free(void* p);
++
++extern void apc_zend_init(TSRMLS_D);
++extern void apc_zend_shutdown(TSRMLS_D);
++
++
++/* offset for apc info in op_array->reserved */
++extern int apc_reserved_offset;
++
++#ifndef ZEND_VM_KIND_CALL /* Not currently defined by any ZE version */
++# define ZEND_VM_KIND_CALL  1
++#endif
++
++#ifndef ZEND_VM_KIND /* Indicates PHP < 5.1 */
++# define ZEND_VM_KIND   ZEND_VM_KIND_CALL
++#endif
++
++#if defined(ZEND_ENGINE_2) && (ZEND_VM_KIND == ZEND_VM_KIND_CALL)
++# define APC_OPCODE_OVERRIDE
++#endif
++
++#ifdef APC_OPCODE_OVERRIDE
++
++#ifdef ZEND_ENGINE_2_1
++/* Taken from Zend/zend_vm_execute.h */
++#define _CONST_CODE  0
++#define _TMP_CODE    1
++#define _VAR_CODE    2
++#define _UNUSED_CODE 3
++#define _CV_CODE     4
++static inline int _apc_opcode_handler_decode(zend_op *opline)
++{
++    static const int apc_vm_decode[] = {
++        _UNUSED_CODE, /* 0              */
++        _CONST_CODE,  /* 1 = IS_CONST   */
++        _TMP_CODE,    /* 2 = IS_TMP_VAR */
++        _UNUSED_CODE, /* 3              */
++        _VAR_CODE,    /* 4 = IS_VAR     */
++        _UNUSED_CODE, /* 5              */
++        _UNUSED_CODE, /* 6              */
++        _UNUSED_CODE, /* 7              */
++        _UNUSED_CODE, /* 8 = IS_UNUSED  */
++        _UNUSED_CODE, /* 9              */
++        _UNUSED_CODE, /* 10             */
++        _UNUSED_CODE, /* 11             */
++        _UNUSED_CODE, /* 12             */
++        _UNUSED_CODE, /* 13             */
++        _UNUSED_CODE, /* 14             */
++        _UNUSED_CODE, /* 15             */
++        _CV_CODE      /* 16 = IS_CV     */
++    };
++    return (opline->opcode * 25) + (apc_vm_decode[opline->op1.op_type] * 5) + apc_vm_decode[opline->op2.op_type];
++}
++
++# define APC_ZEND_OPLINE                    zend_op *opline = execute_data->opline;
++# define APC_OPCODE_HANDLER_DECODE(opline)  _apc_opcode_handler_decode(opline)
++# if PHP_MAJOR_VERSION >= 6
++#  define APC_OPCODE_HANDLER_COUNT          ((25 * 152) + 1)
++# elif PHP_MAJOR_VERSION >= 5 && PHP_MINOR_VERSION >= 3
++#  define APC_OPCODE_HANDLER_COUNT          ((25 * 154) + 1) /* 3 new opcodes in 5.3 - unused, lambda, jmp_set */
++# else
++#  define APC_OPCODE_HANDLER_COUNT          ((25 * 151) + 1)
++# endif
++# define APC_REPLACE_OPCODE(opname)         { int i; for(i = 0; i < 25; i++) if (zend_opcode_handlers[(opname*25) + i]) zend_opcode_handlers[(opname*25) + i] = apc_op_##opname; }
++
++#else /* ZE2.0 */
++# define APC_ZEND_ONLINE
++# define APC_OPCODE_HANDLER_DECODE(opline)  (opline->opcode)
++# define APC_OPCODE_HANDLER_COUNT           512
++# define APC_REPLACE_OPCODE(opname)         zend_opcode_handlers[opname] = apc_op_##opname;
++#endif
++
++#ifndef ZEND_FASTCALL  /* Added in ZE2.3.0 */
++#define ZEND_FASTCALL
++#endif
++
++
++#endif  /* APC_OPCODE_OVERRIDE */
++
++
++#endif  /* APC_ZEND_H */
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/CHANGELOG php-5.3.1/ext/apc/CHANGELOG
+--- php-5.3.1.orig/ext/apc/CHANGELOG   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/CHANGELOG        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,249 @@
++
++3.1.2 : 2008-12-12
++
++- pecl package.xml/build fixes (bjori)
++
++3.1.1 : 2008-12-12
++
++- PHP4 compatibilty break
++- apc_pool allocator (Gopal) 
++- doubly-linked sma allocator (Shire)
++- php 5.3 gc compatibility (Gopal)
++- APCIterator for easy access (Shire)
++- apc_delete_file (Shire)
++- apc_inc/apc_dec/apc_cas functions (Shire)
++- apc.canonicalize (Gopal)
++- apc.preload_path (Gopal)
++- apc.rfc1867_ttl  (Shire)
++- apc.file_md5     (Shire)
++- consolidate locking macros (Shire)
++- remove futex/TSRM locks  (Shire)
++- non-blocking semaphore locks  (Shire)
++- zval* object rework (Gopal)
++
++3.0.19: 2008-05-14
++- Safe-mode and fast-cgi fixes
++- Fix double-free of builtin_functions
++- php 5.3 fixes
++
++3.0.18: 2008-03-29
++- Revert apc_expunge_cb bug-fix
++- Misc memleaks
++
++3.0.17: 2008-03-26
++- Crash fixes
++- Fix apc_add() cache expunge bug (Rasmus)
++- Added parameter to apc_fetch to determine success/failure when fetching booleans (shire)
++- Fix misc. memleaks (shire)
++  
++3.0.16: 2007-12-26
++- Fix for longstanding cache-full crash (Christian Seiler)
++  http://news.php.net/php.pecl.dev/4951 for the details
++- Added optional shm unmap on a fatal signal feature (Lucas Nealan)
++- Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab)
++- Minor cleanups (Lucas Nealan)
++- Added configure option to enable apc_cache_info('filehits') (Shire)
++
++3.0.15: 2007-10-18
++- Eliminate a per-request time() syscall (Rasmus)
++- Added rfc1867 prefix, name, and freq ini options (Shire)
++- Allow deletion of individual user cache entries via apc.php (Sara)
++- Fix overzealous cleanup during RSHUTDOWN (Gopal)
++- Fix memory alignment and locking issues (Gopal) 
++- Make apc_compile insert/replace entries (Shire)
++- Make mixed inheritance recompile & cache afresh  (Gopal)
++- Make nostat mode search include_path for canonicalization (Gopal)
++- ZTS & other compile fixes (Gopal, Edin, Shire)
++  
++3.0.14: 2007-03-21
++- Build fix (Shire)
++- Don't hook the upload hook if APC is disabled (Rasmus)
++- Local shadow cache support (Gopal)
++- Avoid uneccessary loops over op_arrays for "known" auto-globals (Gopal)
++- Fix apc_add() to overwrite timed out user entries (Rasmus)
++- Fix double inclusion of files with conditional classes in php4 (Gopal)
++- Allocator fixes to reduce fragmentation (Gopal)
++
++3.0.13: 2007-02-24
++- File upload progress (Rasmus)
++- Pthread mutex and spin locks (Shire)
++- Recursive zval support for apc_fetch/_store (Shire, Gopal)
++- apc.stat_ctime flag for ctime checks (Rasmus)
++- Multiple key fetches with apc_fetch (Shire)
++- Canary checks for shm memory deallocation (Gopal)
++- Add hooks for external optimizer (Shire)
++- Obsolete and remove apc optimizer (Gopal)
++- APC info changes - cache insert rate, hit and miss rates (Shire)
++- Fix apc_load_constants (Gopal)
++- Rewrite dump opcode code to use vld (Gopal)
++- Use apc_[ewn]print functions for error reporting (Shire) 
++- Auto global fixes and refactoring (Gopal, Shire)
++- Fix memory leaks in object serialization (Ilia)
++- Memory cleanup code for destructor order (Gopal)
++- Win32 build fixes (Ilia, Wez)
++- ZTS and Php 4 build fixes (Bjori)
++- Add apc_add() function (Rasmus)
++- Add optional limited flag to apc_sma_info() (Rasmus)
++
++3.0.12p2: 2006-09-05
++- Package version up
++
++3.0,12p1: 2006-09-05
++- PHP4 build fixes
++
++3.0.12: 2006-09-05
++- PHP 5.2 compatibility (Gopal)
++- TSRM fixes (Gopal)
++- Add extra flags to op_array->reserved to improve op array 
++  processing code (Gopal)
++- Fix crashes in optimizer and cli mode (Ilia)
++- Optimizer fixes for PHP5 (Ilia, Gopal)
++- Allow multiple inclusions of a file with a dynamic class (Gopal)
++- Php 4 function table and properties fixes (Gopal)
++- Fix memory leaks in apc_cache_info (Gopal)
++
++3.0.11: 2006-08-16
++- Made --enable-apc-mmap the default compile option (for real this time)
++- Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
++  only fetch header information to make it useful when you have tens of
++  thousands of entries.  (Brian Shire)
++- 64-bit fixes (George)
++- Don't mix Full Path and Inode keys (George)
++- Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
++  require_once() and include_once() statements. (Sara)
++- Add a non-blocking write_lock for cache inserts.  This is a better approach
++  to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
++- A bit of work on the optimizer.  (Sara)
++- Various memory issues resolved. (Gopal)
++
++3.0.10: 2006-03-11
++- Add apc.stat ini flag which defaults to 1.  If set to 0, the main script and any fullpath
++  includes will not be stat'ed for any changes.  You will have to restart the server if you
++  change anything.  This mode increases performance quite a bit, especially if you have a
++  lot of includes.
++
++- Get rid of the lock safety net hack I added in 3.0.9.  It seems to cause more problems
++  than it solves.  I'll need to revisit locking and signal handling at some point soon.
++
++3.0.9: 2006-03-04
++- Eliminate rand() call when slam_defense is not set (Rasmus)
++- Fix for __isset problem (Gopal)
++- Rewrite allocator from a "best fit" to a "next fit" algorithm (Rasmus)
++- Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
++- Report back the correct number of available bytes in the segment instead of the allocated bytes. (Rasmus)
++- Add cache busy flag which is set when an expunge is underway (Rasmus)
++- Add automatic serialization of objects in apc_store() (Marcus)
++- 64-bit .ini flag fix (Rasmus)
++- Static members fix (Gopal)
++- sma_cleanup() mem leak fix (Rasmus)
++- Fix for http://pecl.php.net/bugs/5311 (Rasmus)
++- Fix autoglobals JIT bug (Gopal)
++- Fix instance bug (Gopal)
++- Add a lock cleanup safety net to request shutdown (Rasmus)
++- Fix apc.slam_defense edge-case bug (Rasmus)
++- User entry memory usage tracking support (Ilia)
++- Allow keys used in apc_store/apc_fetch/apc_delete to be binary safe and prevent conflicts between keys that are found at the start of other keys. (Ilia)
++
++3.0.8: 2005-08-24
++Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
++Cache corruption fix in cache-full cleanup code (Gopal)
++
++3.0.7: 2005-08-16
++- Fix to apc.php to show final segment in frag chart. (Ilia)
++- A couple of win32 fixes. (Frank)
++- Add apc.enable_cli ini directive. (Rasmus)
++- Add test cases. (Marcus)
++- Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
++- Simplify user cache handling by removing the user_cache_stack (Rasmus)
++- Fix apc_fetch() memory corruption (Andrei,Rasmus)
++- Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)
++
++3.0.6: 2005-07-30
++- Added apc.php to package.xml file.
++- Track per-entry memory usage. (Val)
++- Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
++- fcntl locking robustness fixes. (Rasmus)
++- Shared read-locks where possible. (Rasmus)
++- Added file_update_protection configuration parameter. (Rasmus)
++- Windows ZTS fixes (Frank)
++
++3.0.5: 2005-07-27
++- Make it easier for sapis that only populate file_handle->filename to use APC. (Rasmus)
++- Support extensions such as bcompiler that need to hook into compile_file. (Val)
++- Ralf Becker's apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
++- Segfault in cache cleanup code (Ilia, Rasmus)
++
++3.0.4: 2005-07-18
++- Add win32 support (Edin )
++- Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches (Rasmus)
++- A couple of other minor fixes
++
++3.0.3: 2005-07-05
++- Fix compile problem against PHP 5.0.x
++
++3.0.2: 2005-07-05
++- Better shm error message
++
++3.0.1: 2005-07-05
++- PHP4 build fix
++
++3.0: 2005-06-23
++- PHP 5.1 support (Arun, Gopal, Rasmus)
++- Major Inheritance bug fix (Arun, Gopal)
++
++2.0: 2003-02-10
++- ground-up rewrite sharing none of the original source code (djc)
++
++1.0.10:
++- merge mmap / shm code to be in one file, module supports both modes now [mpb 2001-05-15]
++- added apc.mode config parameter [mpb 2001-05-15] NOTE: You'll have to add
++  this parameter to your php.ini file to activate apc shm or mmap caching
++- generic source cleanup (missing includes, PATH_MAX usage etc) [mpb
++  2001-05-15]
++- fixed: realpath return result checking in generate_key [mpb 2001-05-15]
++- updated: gui updated (extras/apc_gui-1.0.2.tar.gz)
++- experminental 'fast' cache-retrieval [djc 2001-05-20]
++- fixed regex support [gws 2001-05-16]
++- enhanced reader-writer lock support [rg 2001-05-07]
++
++1.0.9:
++- fixed (?) memory alignment bug on 64 bit archiecures 
++- added many cache visibiliy functions 
++- added opional fcntl locks under shm version 
++- numerous bug fixes 
++
++1.0.8:
++- added ability to detect and decompile compiled files placed as 'source'
++  [gws,dw 2001-01-30]
++- fixed apc_rstat bug [gws 2001-01-29]
++- added hack to support included urls [gws 2001-01-30]
++- fixed apc_cache_index [mb 2001-01-31]
++- added multiple regex support [gs 2001-02-03]
++- added apc_cache_info [mb,gs 2001-02-03]
++
++1.0.7:
++- partially fixed for Solaris [gws 2001-01-29]
++- fixed mtime support for relative includes [gws 2001-01-29]
++- code cleanup [yg,ta,gws 2001-01-29]
++
++1.0.6:
++- support for mtime in mmap [yg,gws 2001-01-27]
++- fixed indexed-array initialization bug [djc,gws 2001-01-27]
++
++1.0.5:
++- support for relative include paths [djc,gws 2001-01-19]
++- class member array support fixed [djc 2001-01-18]
++- added apc_cache_index [gws 2001-01-18]
++
++1.0.4:
++- support for class hierarchies greater than two levels deep [djc 2001-01-17]
++
++1.0.3:
++- fixed support for class inheritance [djc 2001-01-16]
++
++1.0.2:
++- support for inherited classes [gws 2001-01-15]
++- support for intialization of class variables and objects [gws 2001-01-13]
++
++1.0.1:
++- added optional file modification time check [djc 2001-01-12]
+diff -Naur php-5.3.1.orig/ext/apc/config.m4 php-5.3.1/ext/apc/config.m4
+--- php-5.3.1.orig/ext/apc/config.m4   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/config.m4        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,232 @@
++dnl
++dnl $Id: config.m4 286829 2009-08-05 10:31:28Z gopalv $
++dnl
++
++PHP_ARG_ENABLE(apc, whether to enable APC support,
++[  --enable-apc           Enable APC support])
++
++AC_MSG_CHECKING(whether we should enable cache request file info)
++AC_ARG_ENABLE(apc-filehits,
++[  --enable-apc-filehits   Enable per request file info about files used from the APC cache (ie: apc_cache_info('filehits')) ],
++[
++  PHP_APC_FILEHITS=$enableval
++      AC_MSG_RESULT($enableval)
++], 
++[
++  PHP_APC_FILEHITS=no
++      AC_MSG_RESULT(no)
++])
++
++AC_MSG_CHECKING(whether we should use mmap)
++AC_ARG_ENABLE(apc-mmap,
++[  --disable-apc-mmap
++                          Disable mmap support and use IPC shm instead],
++[
++  PHP_APC_MMAP=$enableval
++  AC_MSG_RESULT($enableval)
++], [
++  PHP_APC_MMAP=yes
++  AC_MSG_RESULT(yes)
++])
++
++AC_MSG_CHECKING(whether we should use semaphore locking instead of fcntl)
++AC_ARG_ENABLE(apc-sem,
++[  --enable-apc-sem
++                          Enable semaphore locks instead of fcntl],
++[
++  PHP_APC_SEM=$enableval
++  AC_MSG_RESULT($enableval)
++], [
++  PHP_APC_SEM=no
++  AC_MSG_RESULT(no)
++])
++
++AC_MSG_CHECKING(whether we should use pthread mutex locking)
++AC_ARG_ENABLE(apc-pthreadmutex,
++[  --disable-apc-pthreadmutex
++                          Disable pthread mutex locking ],
++[
++  PHP_APC_PTHREADMUTEX=$enableval
++  AC_MSG_RESULT($enableval)
++],
++[
++  PHP_APC_PTHREADMUTEX=yes
++  AC_MSG_RESULT(yes)
++])
++
++if test "$PHP_APC_PTHREADMUTEX" != "no"; then
++      orig_LIBS="$LIBS"
++      LIBS="$LIBS -lpthread"
++      AC_TRY_RUN(
++                      [
++                              #include <sys/types.h>
++                              #include <pthread.h>
++                                main() {
++                              pthread_mutex_t mutex;
++                              pthread_mutexattr_t attr;       
++
++                              if(pthread_mutexattr_init(&attr)) { 
++                                      puts("Unable to initialize pthread attributes (pthread_mutexattr_init).");
++                                      return -1; 
++                              }
++                              if(pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED)) { 
++                                      puts("Unable to set PTHREAD_PROCESS_SHARED (pthread_mutexattr_setpshared), your system may not support shared mutex's.");
++                                      return -1; 
++                              }       
++                              if(pthread_mutex_init(&mutex, &attr)) { 
++                                      puts("Unable to initialize the mutex (pthread_mutex_init).");
++                                      return -1; 
++                              }
++                              if(pthread_mutexattr_destroy(&attr)) { 
++                                      puts("Unable to destroy mutex attributes (pthread_mutexattr_destroy).");
++                                      return -1; 
++                              }
++                              if(pthread_mutex_destroy(&mutex)) { 
++                                      puts("Unable to destroy mutex (pthread_mutex_destroy).");
++                                      return -1; 
++                              }
++
++                              puts("pthread mutex's are supported!");
++                              return 0;
++                                }
++                      ],
++                      [ dnl -Success-
++                              PHP_ADD_LIBRARY(pthread)
++                      ],
++                      [ dnl -Failure-
++                              AC_MSG_WARN([It doesn't appear that pthread mutex's are supported on your system])
++                      PHP_APC_PTHREADMUTEX=no
++                      ],
++                      [
++                              PHP_ADD_LIBRARY(pthread)
++                      ]
++      )
++      LIBS="$orig_LIBS"
++fi
++
++AC_MSG_CHECKING(whether we should use spin locks)
++AC_ARG_ENABLE(apc-spinlocks,
++[  --enable-apc-spinlocks
++                          Enable spin locks  EXPERIMENTAL ],
++[
++  PHP_APC_SPINLOCKS=$enableval
++  AC_MSG_RESULT($enableval)
++],
++[
++  PHP_APC_SPINLOCKS=no
++  AC_MSG_RESULT(no)
++])
++
++AC_MSG_CHECKING(whether we should enable memory protection)
++AC_ARG_ENABLE(memory-protection,
++[  --enable-memory-protection
++                          Enable mmap/shm memory protection],
++[
++  PHP_APC_MEMPROTECT=$enableval
++  AC_MSG_RESULT($enableval)
++], [
++  PHP_APC_MEMPROTECT=no
++  AC_MSG_RESULT(no)
++])
++
++if test "$PHP_APC" != "no"; then
++  test "$PHP_APC_MMAP" != "no" && AC_DEFINE(APC_MMAP, 1, [ ])
++  test "$PHP_APC_FILEHITS" != "no" && AC_DEFINE(APC_FILEHITS, 1, [ ])
++
++      if test "$PHP_APC_SEM" != "no"; then
++              AC_DEFINE(APC_SEM_LOCKS, 1, [ ])
++      elif test "$PHP_APC_SPINLOCKS" != "no"; then
++              AC_DEFINE(APC_SPIN_LOCKS, 1, [ ]) 
++      elif test "$PHP_APC_PTHREADMUTEX" != "no"; then 
++              AC_DEFINE(APC_PTHREADMUTEX_LOCKS, 1, [ ])
++      else 
++              AC_DEFINE(APC_FCNTL_LOCKS, 1, [ ])
++      fi
++  
++      if test "$PHP_APC_MEMPROTECT" != "no"; then
++              AC_DEFINE(APC_MEMPROTECT, 1, [ shm/mmap memory protection ])
++      fi
++
++  AC_CACHE_CHECK(for zend_set_lookup_function_hook, php_cv_zend_set_lookup_function_hook,
++  [
++    orig_cflags=$CFLAGS
++    CFLAGS="$INCLUDES $EXTRA_INCLUDES"
++    AC_TRY_COMPILE([
++#include "main/php.h"
++#include "Zend/zend_API.h"
++    ], [#ifndef zend_set_lookup_function_hook
++      (void) zend_set_lookup_function_hook;
++#endif], [
++      php_cv_zend_set_lookup_function_hook=yes
++    ],[
++      php_cv_zend_set_lookup_function_hook=no
++    ])
++    CFLAGS=$orig_cflags
++  ])
++  if test "$php_cv_zend_set_lookup_function_hook" = "yes"; then
++    AC_DEFINE(APC_HAVE_LOOKUP_HOOKS, 1, [ ])
++  else
++    AC_DEFINE(APC_HAVE_LOOKUP_HOOKS, 0, [ ])
++  fi
++
++  AC_CHECK_FUNCS(sigaction)
++  AC_CACHE_CHECK(for union semun, php_cv_semun,
++  [
++    AC_TRY_COMPILE([
++#include <sys/types.h>
++#include <sys/ipc.h>
++#include <sys/sem.h>
++    ], [union semun x; x.val=1], [
++      php_cv_semun=yes
++    ],[
++      php_cv_semun=no
++    ])
++  ])
++  if test "$php_cv_semun" = "yes"; then
++    AC_DEFINE(HAVE_SEMUN, 1, [ ])
++  else
++    AC_DEFINE(HAVE_SEMUN, 0, [ ])
++  fi
++
++  AC_MSG_CHECKING(whether we should enable valgrind support)
++  AC_ARG_ENABLE(valgrind-checks,
++  [  --disable-valgrind-checks
++                          Disable valgrind based memory checks],
++  [
++    PHP_APC_VALGRIND=$enableval
++    AC_MSG_RESULT($enableval)
++  ], [
++    PHP_APC_VALGRIND=yes
++    AC_MSG_RESULT(yes)
++    AC_CHECK_HEADER(valgrind/memcheck.h, 
++              [AC_DEFINE([HAVE_VALGRIND_MEMCHECK_H],1, [enable valgrind memchecks])])
++  ])
++
++  apc_sources="apc.c php_apc.c \
++               apc_cache.c \
++               apc_compile.c \
++               apc_debug.c \
++               apc_fcntl.c \
++               apc_main.c \
++               apc_mmap.c \
++               apc_sem.c \
++               apc_shm.c \
++               apc_pthreadmutex.c \
++               apc_spin.c \
++               pgsql_s_lock.c \
++               apc_sma.c \
++               apc_stack.c \
++               apc_zend.c \
++               apc_rfc1867.c \
++               apc_signal.c \
++               apc_pool.c \
++               apc_iterator.c \
++               apc_bin.c "
++
++  PHP_CHECK_LIBRARY(rt, shm_open, [PHP_ADD_LIBRARY(rt,,APC_SHARED_LIBADD)])
++  PHP_NEW_EXTENSION(apc, $apc_sources, $ext_shared,, \\$(APC_CFLAGS))
++  PHP_SUBST(APC_SHARED_LIBADD)
++  PHP_SUBST(APC_CFLAGS)
++  AC_DEFINE(HAVE_APC, 1, [ ])
++fi
++
+diff -Naur php-5.3.1.orig/ext/apc/config.w32 php-5.3.1/ext/apc/config.w32
+--- php-5.3.1.orig/ext/apc/config.w32  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/config.w32       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,27 @@
++// $Id: config.w32 284592 2009-07-22 10:53:50Z kalle $
++// vim:ft=javascript
++
++ARG_ENABLE("apc", "Alternative PHP Cache", "no");
++
++if (PHP_APC != "no") {
++      apc_sources="apc.c php_apc.c \
++                                                       apc_cache.c \
++                                                       apc_compile.c \
++                                                       apc_debug.c \
++                                                       apc_fcntl_win32.c \
++                                                       apc_iterator.c \
++                                                       apc_main.c \
++                                                       apc_shm.c \
++                                                       apc_sma.c \
++                                                       apc_stack.c \
++                                                       apc_rfc1867.c \
++                                                       apc_zend.c \
++                                                       apc_pool.c \
++                                                       apc_bin.c \
++                                                       apc_spin.c \
++                                                       pgsql_s_lock.c";
++               
++      EXTENSION('apc', apc_sources);
++      AC_DEFINE('HAVE_APC', 1);
++      ADD_FLAG('CFLAGS_APC', "/DAPC_SPIN_LOCKS=1 /DWIN32_ONLY_COMPILER=1");
++}
+diff -Naur php-5.3.1.orig/ext/apc/INSTALL php-5.3.1/ext/apc/INSTALL
+--- php-5.3.1.orig/ext/apc/INSTALL     1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/INSTALL  1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,421 @@
++Installation Instructions for APC
++---------------------------------
++
++This version of APC should work on PHP 4.3.0 - 4.4.x and
++5.1.0 - 5.2.x.  Yes, that means PHP 5.0.x is no longer 
++supported.  Upgrade to PHP 5.1.x or 5.2.x and you will 
++notice all sorts of performance increases.
++
++CVS Instructions
++----------------
++Building from CVS can be done like this:
++
++  cvs -d :pserver:cvsread@cvs.php.net:/repository login
++  Password: phpfi
++  cvs -d :pserver:cvsread@cvs.php.net:/repository co pecl/apc
++  cd pecl/apc
++  phpize
++  ./configure --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
++  make
++  make install
++
++Suggested Configuration (in your php.ini file)
++----------------------------------------------
++  extension=apc.so
++  apc.enabled=1
++  apc.shm_segments=1
++  apc.shm_size=128
++  apc.ttl=7200
++  apc.user_ttl=7200
++  apc.num_files_hint=1024
++  apc.mmap_file_mask=/tmp/apc.XXXXXX
++  apc.enable_cli=1
++
++These are fully described at the bottom of this file.
++
++PHP 4 Optimization
++------------------
++If you are trying to get every little bit of speed out of PHP4+APC, you need
++to tell APC where to find your httpd.h file and also add -DAPC_PHP4_STAT to
++your CPPFLAGS.  (if you don't have httpd.h, install the apache_dev package 
++for your OS) and do:
++  export CPPFLAGS="-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for bash on Debian)
++  setenv CPPFLAGS "-I/usr/include/apache-1.3 -DAPC_PHP4_STAT" (for tsch on Debian)
++and then re-run your configure script.
++
++This optimization saves a stat syscall on the main script file.  In PHP5 this
++optimization is automatic and doesn't need any special build flags.
++
++The second thing you are going to want to do to save another syscall is to 
++compile using the --with-apxs configure switch.  This should work for both
++Apache1 and Apache2.  Point it directly at your apxs2 script for Apache2.
++eg. --with-apxs=/usr/local/bin/apxs2
++
+++---------------------+
++| QUICK INSTALL (DSO) |
+++---------------------+
++
++These instructions assume your PHP installation is located in /usr/local/php and you
++want Apache optimizations (--with-apxs).
++
++$ gunzip -c apc_x.y.tar.gz | tar xf -
++$ cd apc_x.y
++$ /usr/local/php/bin/phpize
++$ ./configure --enable-apc --enable-apc-mmap --with-apxs --with-php-config=/usr/local/php/bin/php-config
++$ make
++$ make install
++
++You will probably need to run the final command (make install) as root.
++
++The above sequence of commands will install a .so file in your PHP
++installation extension directory. The output of make install should display
++that path to the screen.
++
++Next you must edit your php.ini file, which is normally located in
++/usr/local/php/lib/php.ini, and add the following line:
++
++    extension="apc.so"
++
++Replace "/path/to/php/extensions" with whatever path was displayed when you
++ran make install above.
++
++Then restart your web server and consult the output of phpinfo(). If there is
++an informational section for APC, the installation was successful.
++
+++------------------------+
++| QUICK INSTALL (Static) |
+++------------------------+
++
++APC will not successfully compile on all systems as a DSO. If you run into
++problems using the DSO quick install, you can try to compile it statically
++into PHP. (The DSO install is recommended, though.)
++
++These instructions assume the current directory is the root of the PHP source
++tree, and that you have already configured PHP by running its bundled
++configure script.
++
++$ cd ext
++$ gunzip -c apc_x.y.tar.gz | tar xf -
++$ cd ..
++$ ./buildconf
++$ ./config.nice
++$ make
++$ make install
++
++Once this is complete, simply restart your web server. You do not need to
++modify your php.ini file to enable APC.
++
+++-----------------+
++| VERBOSE INSTALL |
+++-----------------+
++
++These instructions assume your PHP installation is located in /usr/local/php.
++
++1.  Unpack your distribution file.
++
++    You will have downloaded a file named something like apc_x.y.tar.gz.
++    Unzip this file with a command like
++    
++        gunzip apc_x.y.tar.gz
++    
++    Next you have to untar it with
++    
++        tar xvf apc_x.y.tar
++
++    This will create an apc_x.y directory. cd into this new directory:
++
++        cd apc_x.y
++
++2.  Run phpize.
++
++    phpize is a script that should have been installed with PHP, and is
++    normally located in /usr/local/php/bin assuming you installed PHP in
++    /usr/local/php. (If you do not have the phpize script, you must reinstall
++    PHP and be sure not to disable PEAR.)
++
++    Run the phpize command:
++    
++        /usr/local/php/bin/phpize
++
++    Its output should resemble this:
++
++        autoheader: `config.h.in' is created
++        You should update your `aclocal.m4' by running aclocal.
++        Configuring for:
++          PHP Api Version:   20020918
++          Zend Module Api No:   20020429
++          Zend Extension Api No:   20021010
++ 
++    phpize should create a configure script in the current directory. If you
++    get errors instead, you might be missing some required development tools,
++    such as autoconf or libtool. You can try downloading the latest versions
++    of those tools and running phpize again.
++ 
++3.  Run the configure script.
++ 
++    phpize creates a configure script. The only option you need to specify is
++    the location of your php-config script:
++
++        ./configure --enable-apc
++
++    php-config should be located in the same directory as phpize.
++
++    If you prefer to use mmap instead of the default IPC shared memory support,
++    add --enable-apc-mmap to your configure line. 
++
++      If you prefer to use sysv IPC semaphores over the safer fcntl() locks, add
++      --enable-sem to your configure line.  If you don't have a problem
++      with your server segaulting, or any other unnatural accumulation of
++      semaphores on your system, the semaphore based locking is slightly faster.
++
++4.  Compile and install the files. Simply type: make install
++
++    (You may need to be root in order to install)
++
++    If you encounter errors from libtool or gcc during this step, please
++    contact the project maintainer (dcowgill@php.net).
++
++5.  Edit your php.ini
++
++    make install should have printed a line resembling the following:
++
++        Installing shared extensions: /path/to/extension/
++
++    Copy the path /path/to/extension/ and add the following line to your
++    php.ini file (normally located in /usr/local/php/lib/php.ini):
++
++        extension="apc.so"
++
++    If you don't have a php.ini file in that location, you can create it now.
++
++6.  Restart the web server and test the installation.
++
++    Restart your web server now (for apache, it's apachectl restart) and
++    create a small test PHP file in your document root. The file should
++    contain just the following line:
++
++        <?php phpinfo() ?>
++
++    Request that file in a web browser. If there is an entry for APC in the
++    list of installed modules, the installation was successful.
++
++    If APC is not listed, consult your web server error log. If it contains an
++    error message saying that it can't load the APC extension, your system
++    might not be able to load shared libraries created with PHP's build
++    system. One alternative would be to compile APC statically into PHP. See
++    the Quick Install (Static) instructions above.
++
++    You should consult your error log anyway to see if APC generated any
++    errors. On BSD-based platforms, it is typical for APC to be unable to
++    allocate the default-sized shared memory segment. See below for hints on
++    raising your system's shared memory limitations.
++
+++-----------------+
++| CONFIGURING APC |
+++-----------------+
++
++Although the default APC settings are fine for many installations, serious
++users should consider tuning the following parameters:
++
++    OPTION                  DESCRIPTION
++    ------------------      --------------------------------------------------
++    apc.enabled             This can be set to 0 to disable APC. This is
++                            primarily useful when APC is statically compiled
++                            into PHP, since there is no other way to disable
++                            it (when compiled as a DSO, the zend_extension
++                            line can just be commented-out).
++                            (Default: 1)
++                            
++    apc.shm_segments        The number of shared memory segments to allocate
++                            for the compiler cache. If APC is running out of
++                            shared memory but you have already set
++                            apc.shm_size as high as your system allows, you
++                            can try raising this value.  Setting this to a
++                            value other than 1 has no effect in mmap mode
++                            since mmap'ed shm segments don't have size limits.
++                            (Default: 1)
++                            
++    apc.shm_size            The size of each shared memory segment in MB.
++                            By default, some systems (including most BSD
++                            variants) have very low limits on the size of a
++                            shared memory segment.
++                            (Default: 30)
++                            
++    apc.optimization        This option has been deprecated.
++                            (Default: 0)
++    
++    apc.num_files_hint      A "hint" about the number of distinct source files
++                            that will be included or requested on your web
++                            server. Set to zero or omit if you're not sure;
++                            this setting is mainly useful for sites that have
++                            many thousands of source files.
++                            (Default: 1000)
++
++    apc.user_entries_hint   Just like num_files_hint, a "hint" about the number
++                            of distinct user cache variables to store. 
++                            Set to zero or omit if you're not sure;
++                            (Default: 4096)
++
++    apc.ttl                 The number of seconds a cache entry is allowed to
++                            idle in a slot in case this cache entry slot is 
++                            needed by another entry.  Leaving this at zero
++                            means that your cache could potentially fill up
++                            with stale entries while newer entries won't be
++                            cached.  
++                            (Default: 0)
++
++    apc.user_ttl            The number of seconds a user cache entry is allowed 
++                            to idle in a slot in case this cache entry slot is 
++                            needed by another entry.  Leaving this at zero
++                            means that your cache could potentially fill up
++                            with stale entries while newer entries won't be
++                            cached.  
++                            (Default: 0)
++
++
++    apc.gc_ttl              The number of seconds that a cache entry may
++                            remain on the garbage-collection list. This value
++                            provides a failsafe in the event that a server
++                            process dies while executing a cached source file;
++                            if that source file is modified, the memory
++                            allocated for the old version will not be
++                            reclaimed until this TTL reached. Set to zero to
++                            disable this feature.
++                            (Default: 3600)
++
++    apc.cache_by_default    On by default, but can be set to off and used in
++                            conjunction with positive apc.filters so that files
++                            are only cached if matched by a positive filter.
++                            (Default: On)
++
++    apc.filters             A comma-separated list of POSIX extended regular
++                            expressions. If any pattern matches the source
++                            filename, the file will not be cached. Note that
++                            the filename used for matching is the one passed
++                            to include/require, not the absolute path.  If the
++                            first character of the expression is a + then the
++                            expression will be additive in the sense that any
++                            files matched by the expression will be cached, and
++                            if the first character is a - then anything matched
++                            will not be cached.  The - case is the default, so
++                            it can be left off.
++                            (Default: "")
++
++    apc.mmap_file_mask      If compiled with MMAP support by using --enable-mmap
++                            this is the mktemp-style file_mask to pass to the
++                            mmap module for determing whether your mmap'ed memory
++                            region is going to be file-backed or shared memory
++                            backed.  For straight file-backed mmap, set it to
++                            something like /tmp/apc.XXXXXX (exactly 6 X's).
++                            To use POSIX-style shm_open/mmap put a ".shm"
++                            somewhere in your mask.  eg.  "/apc.shm.XXXXXX"
++                            You can also set it to "/dev/zero" to use your 
++                            kernel's /dev/zero interface to anonymous mmap'ed 
++                            memory.  Leaving it undefined will force an 
++                            anonymous mmap.
++                            (Default: "")
++
++    apc.slam_defense        ** DEPRECATED - Use apc.write_lock instead **
++                            On very busy servers whenever you start the server or
++                            modify files you can create a race of many processes
++                            all trying to cache the same file at the same time.
++                            This option sets the percentage of processes that will
++                            skip trying to cache an uncached file.  Or think of it
++                            as the probability of a single process to skip caching.
++                            For example, setting this to 75 would mean that there is
++                            a 75% chance that the process will not cache an uncached
++                            file.  So the higher the setting the greater the defense
++                            against cache slams.  Setting this to 0 disables this
++                            feature.
++                            (Default: 0)
++
++    apc.file_update_protection
++                            When you modify a file on a live web server you really
++                            should do so in an atomic manner.  That is, write to a
++                            temporary file and rename (mv) the file into its permanent
++                            position when it is ready.  Many text editors, cp, tar and
++                            other such programs don't do this.  This means that there
++                            is a chance that a file is accessed (and cached) while it
++                            is still being written to.  This file_update_protection
++                            setting puts a delay on caching brand new files.  The
++                            default is 2 seconds which means that if the modification
++                            timestamp (mtime) on a file shows that it is less than 2
++                            seconds old when it is accessed, it will not be cached.  
++                            The unfortunate person who accessed this half-written file
++                            will still see weirdness, but at least it won't persist.
++                            If you are certain you always atomically update your files
++                            by using something like rsync which does this correctly, you
++                            can turn this protection off by setting it to 0.  If you
++                            have a system that is flooded with io causing some update
++                            procedure to take longer than 2 seconds, you may want to
++                            increase this a bit.
++                            (Default: 2)
++
++    apc.enable_cli          Mostly for testing and debugging.  Setting this enables APC
++                            for the CLI version of PHP.  Normally you wouldn't want to
++                            create, populate and tear down the APC cache on every CLI
++                            request, but for various test scenarios it is handy to be
++                            able to enable APC for the CLI version of APC easily.
++                            (Default: 0)
++
++    apc.max_file_size       Prevents large files from being cached.  
++                            (Default: 1M)
++
++    apc.stat                Whether to stat the main script file and the fullpath
++                            includes.  If you turn this off you will need to restart
++                            your server in order to update scripts.
++                            (Default: 1)
++
++    apc.canonicalize        Whether to canonicalize paths in stat=0 mode or
++                            fall back to stat behaviour if set to 0
++                            (Default: 0)
++
++    apc.write_lock          On busy servers when you first start up the server, or when
++                            many files are modified, you can end up with all your processes
++                            trying to compile and cache the same files.  With write_lock 
++                            enabled, only one process at a time will try to compile an
++                            uncached script while the other processes will run uncached
++                            instead of sitting around waiting on a lock.
++                            (Default: 1)
++
++    apc.report_autofilter   Logs any scripts that were automatically excluded from being
++                            cached due to early/late binding issues.
++                            (Default: 0)
++
++    apc.rfc1867             RFC1867 File Upload Progress hook handler is only available
++                            if you compiled APC against PHP 5.2.0 or later.  When enabled
++                            any file uploads which includes a field called 
++                            APC_UPLOAD_PROGRESS before the file field in an upload form
++                            will cause APC to automatically create an upload_<key>
++                            user cache entry where <key> is the value of the 
++                            APC_UPLOAD_PROGRESS form entry.
++
++                            Note that the file upload tracking is not threadsafe at this
++                            point, so new uploads that happen while a previous one is 
++                            still going will disable the tracking for the previous.
++                            (Default: 0)
++
++    apc.rfc1867_prefix      Key prefix to use for the user cache entry generated by
++                            rfc1867 upload progress functionality.  
++                            (Default: "upload_")
++
++    apc.rfc1867_name        Specify the hidden form entry name that activates APC upload
++                            progress and specifies the user cache key suffix.
++                            (Default: "APC_UPLOAD_PROGRESS")
++
++    apc.rfc1867_freq        The frequency that updates should be made to the user cache
++                            entry for upload progress.  This can take the form of a 
++                            percentage of the total file size or a size in bytes 
++                            optionally suffixed with 'k', 'm', or 'g' for kilobytes, 
++                            megabytes, or gigabytes respectively (case insensitive).  
++                            A setting of 0 updates as often as possible, which may cause 
++                            slower uploads.
++                            (Default: 0)
++
++    apc.localcache         ** REMOVED 
++    apc.localcache.size    ** REMOVED
++    
++    apc.include_once_override 
++                            Optimize include_once and require_once calls and avoid the 
++                            expensive system calls used.
++                            (Default: 0)
+diff -Naur php-5.3.1.orig/ext/apc/LICENSE php-5.3.1/ext/apc/LICENSE
+--- php-5.3.1.orig/ext/apc/LICENSE     1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/LICENSE  1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,68 @@
++-------------------------------------------------------------------- 
++                  The PHP License, version 3.01
++Copyright (c) 1999 - 2006 The PHP Group. All rights reserved.
++-------------------------------------------------------------------- 
++
++Redistribution and use in source and binary forms, with or without
++modification, is permitted provided that the following conditions
++are met:
++
++  1. Redistributions of source code must retain the above copyright
++     notice, this list of conditions and the following disclaimer.
++ 
++  2. Redistributions in binary form must reproduce the above copyright
++     notice, this list of conditions and the following disclaimer in
++     the documentation and/or other materials provided with the
++     distribution.
++ 
++  3. The name "PHP" must not be used to endorse or promote products
++     derived from this software without prior written permission. For
++     written permission, please contact group@php.net.
++  
++  4. Products derived from this software may not be called "PHP", nor
++     may "PHP" appear in their name, without prior written permission
++     from group@php.net.  You may indicate that your software works in
++     conjunction with PHP by saying "Foo for PHP" instead of calling
++     it "PHP Foo" or "phpfoo"
++ 
++  5. The PHP Group may publish revised and/or new versions of the
++     license from time to time. Each version will be given a
++     distinguishing version number.
++     Once covered code has been published under a particular version
++     of the license, you may always continue to use it under the terms
++     of that version. You may also choose to use such covered code
++     under the terms of any subsequent version of the license
++     published by the PHP Group. No one other than the PHP Group has
++     the right to modify the terms applicable to covered code created
++     under this License.
++
++  6. Redistributions of any form whatsoever must retain the following
++     acknowledgment:
++     "This product includes PHP software, freely available from
++     <http://www.php.net/software/>".
++
++THIS SOFTWARE IS PROVIDED BY THE PHP DEVELOPMENT TEAM ``AS IS'' AND 
++ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
++THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
++PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE PHP
++DEVELOPMENT TEAM OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
++INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
++(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
++SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
++HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
++ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
++OF THE POSSIBILITY OF SUCH DAMAGE.
++
++-------------------------------------------------------------------- 
++
++This software consists of voluntary contributions made by many
++individuals on behalf of the PHP Group.
++
++The PHP Group can be contacted via Email at group@php.net.
++
++For more information on the PHP Group and the PHP project, 
++please see <http://www.php.net>.
++
++PHP includes the Zend Engine, freely available at
++<http://www.zend.com>.
+diff -Naur php-5.3.1.orig/ext/apc/NOTICE php-5.3.1/ext/apc/NOTICE
+--- php-5.3.1.orig/ext/apc/NOTICE      1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/NOTICE   1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,43 @@
++This is the NOTICE file that holds acknowledgements and stuff.
++
++The Alternative PHP Cache (APC) is a free and open opcode cache for PHP.
++This extension is being released under the PHP License for complete compliance
++with PHP and to encourage wide-spread use.  It is our intention that this
++project be kept open source and that all commercial spin-offs contribute their
++modifications back into the public source-tree.
++
++Creators:
++    Daniel Cowgill
++    George Schlossnagle
++
++PHP5 support and major features by:
++    Arun C. Murthy 
++    Gopal Vijayaraghavan
++    Rasmus Lerdorf
++
++This software was contributed to PHP by Community Connect Inc. in 2002
++and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++Future revisions and derivatives of this source code must acknowledge
++Community Connect Inc. as the original contributor of this module by
++leaving this note intact in the source code.
++
++All other licensing and usage conditions are those of the PHP Group.
++
++We would like to thank Community Connect Inc. and Yahoo! Inc. for supporting 
++this project and providing a challenging and stimulating environment in 
++which exciting projects can happen.
++
++Contributors:
++    Mike Bretz          bug fixes, GUI, and lots of work
++    Ricardo Galli       changed read-write locks to prefer readers
++    Yann Grossel        bug fixes
++    Thies Arntzen       bug fixes
++    Sara Golemon        optimizer work
++
++Special Thanks:
++    Florian Baumert     help debugging phplib problems
++    Thomas Duffey       help debugging inheritance issues
++    Vibol Hou           help debugging phplib problems
++    Angel Li            diffs for ANSI comment compliance
++    Christian Rishøj    help debugging phplib problems
++    Sascha Schumann     memory error bug fix
+diff -Naur php-5.3.1.orig/ext/apc/package.xml php-5.3.1/ext/apc/package.xml
+--- php-5.3.1.orig/ext/apc/package.xml 1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/package.xml      1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,736 @@
++<?xml version="1.0" encoding="UTF-8"?>
++<package packagerversion="1.8.0" version="2.0" xmlns="http://pear.php.net/dtd/package-2.0" xmlns:tasks="http://pear.php.net/dtd/tasks-1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://pear.php.net/dtd/tasks-1.0 http://pear.php.net/dtd/tasks-1.0.xsd http://pear.php.net/dtd/package-2.0 http://pear.php.net/dtd/package-2.0.xsd">
++ <name>APC</name>
++ <channel>pecl.php.net</channel>
++ <summary>Alternative PHP Cache</summary>
++ <description>APC is a free, open, and robust framework for caching and optimizing PHP intermediate code.</description>
++ <lead>
++  <name>Daniel Cowgill</name>
++  <user>dcowgill</user>
++  <email>dan@mail.communityconnect.com</email>
++  <active>no</active>
++ </lead>
++ <lead>
++  <name>George Schlossnagle</name>
++  <user>gschlossnagle</user>
++  <email>george@omniti.com</email>
++  <active>no</active>
++ </lead>
++ <lead>
++  <name>Rasmus Lerdorf</name>
++  <user>rasmus</user>
++  <email>rasmus@php.net</email>
++  <active>yes</active>
++ </lead>
++ <lead>
++  <name>Gopal Vijayaraghavan</name>
++  <user>gopalv</user>
++  <email>gopalv@php.net</email>
++  <active>yes</active>
++ </lead>
++ <developer>
++  <name>Edin Kadribasic</name>
++  <user>edink</user>
++  <email>edink@emini.dk</email>
++  <active>yes</active>
++ </developer>
++ <developer>
++  <name>Ilia Alshanetsky</name>
++  <user>iliaa</user>
++  <email>ilia@prohost.org</email>
++  <active>yes</active>
++ </developer>
++ <developer>
++  <name>Marcus Börger</name>
++  <user>helly</user>
++  <email>helly@php.net</email>
++  <active>yes</active>
++ </developer>
++ <developer>
++  <name>Sara Golemon</name>
++  <user>pollita</user>
++  <email>pollita@php.net</email>
++  <active>yes</active>
++ </developer>
++ <developer>
++  <name>Brian Shire</name>
++  <user>shire</user>
++  <email>shire@php.net</email>
++  <active>yes</active>
++ </developer>
++ <date>2009-08-14</date>
++ <time>16:30:36</time>
++ <version>
++  <release>3.1.3p1</release>
++  <api>3.1.0</api>
++ </version>
++ <stability>
++  <release>beta</release>
++  <api>beta</api>
++ </stability>
++ <license uri="http://www.php.net/license">PHP License</license>
++ <notes>
++- fix pecl build / package.xml (Gopal)
++ </notes>
++ <contents>
++  <dir name="/">
++   <file md5sum="841596cff3b9bd83e79d01ccb591ff55" name="tests/apc_001.phpt" role="test" />
++   <file md5sum="cc1dba4e429ff93dce1ca7dea01c2899" name="tests/apc_002.phpt" role="test" />
++   <file md5sum="04c800594e9934cf8e15157e9bd4c52f" name="tests/apc_003.phpt" role="test" />
++   <file md5sum="538f198f432614d9f2c0819fea5193a7" name="tests/apc_003b.phpt" role="test" />
++   <file md5sum="43c8e1c89fad5bb25ded528837e63b2b" name="tests/apc_004.phpt" role="test" />
++   <file md5sum="06432141cbc82df8ddde7fac52e9f65e" name="tests/apc_005.phpt" role="test" />
++   <file md5sum="74f802b99f111d1cdab6abaf20edae95" name="tests/apc_006.phpt" role="test" />
++   <file md5sum="b724592cd9629ab5e9dac9f1ef5d3e10" name="tests/apc_007.phpt" role="test" />
++   <file md5sum="0674cbe2e88fe5c331bee3fbb1395d4f" name="tests/apc_008.phpt" role="test" />
++   <file md5sum="4092ea60d4ff7bfdcbcc5795c06e60e7" name="tests/apc_009.phpt" role="test" />
++   <file md5sum="6640964ee33a683b1693b545d1ff2ed0" name="tests/apc_010.phpt" role="test" />
++   <file md5sum="611e5e725d57fcca216bf79778238290" name="tests/apc53_001.phpt" role="test" />
++   <file md5sum="1cd474d5a3567601d66d1078699fd587" name="tests/apc53_002.phpt" role="test" />
++   <file md5sum="3d863bb88c5f2624320b7b72e368d668" name="tests/apc53_003.phpt" role="test" />
++   <file md5sum="128e9590ff8d3d0791a1ef9ce9c078f5" name="tests/apc53_004.phpt" role="test" />
++   <file md5sum="c710a33310dfacef4d51cb721855857e" name="tests/apc53_005.phpt" role="test" />
++   <file md5sum="4b7dc1553dadcb3378d33e069387e35c" name="tests/apc_bin_001.phpt" role="test" />
++   <file md5sum="c992d44557b849a10984b089419d2e01" name="tests/apc_bin_002-1.inc" role="test" />
++   <file md5sum="409cadd9efc9d863421b15d63d8c6515" name="tests/apc_bin_002-2.inc" role="test" />
++   <file md5sum="2667d74094dac9e366020c11b3a9bd47" name="tests/apc_bin_002.phpt" role="test" />
++   <file md5sum="1bb542e50a5e6eb06b54a89ceaa81976" name="tests/iterator_001.phpt" role="test" />
++   <file md5sum="7ee077f992cd81940f74b5f1b0e885c0" name="tests/iterator_002.phpt" role="test" />
++   <file md5sum="eccbaee4d483213ee8ba0583c705224b" name="tests/iterator_003.phpt" role="test" />
++   <file md5sum="4ec172b4fc8ed2f45f3d7426865a0db5" name="tests/iterator_004.phpt" role="test" />
++   <file md5sum="eec4bf6bdfa4936cb122845216cad7e0" name="tests/iterator_005.phpt" role="test" />
++   <file md5sum="3206db85017077ed498fd9d5ac7585e7" name="tests/iterator_006.phpt" role="test" />
++   <file md5sum="82a40b37c545631cd87c3e1e421353b5" name="tests/iterator_007.phpt" role="test" />
++   <file md5sum="92e7b033fac8b625c6ad52e21d1222bf" name="tests/php_5_3_ns.inc" role="test" />
++   <file md5sum="6ecba4154b6bd6f8703000f5198710cc" name="tests/skipif.inc" role="test" />
++   <file md5sum="ed9a4192d7ab7f953856b92c5e689cf5" name="CHANGELOG" role="doc" />
++   <file md5sum="f5ca8db7fde5fb83ab79b509279b9856" name="INSTALL" role="doc" />
++   <file md5sum="694f49a7e1f276ba75a3dd2c5acd580d" name="LICENSE" role="doc" />
++   <file md5sum="eea150699d3dffb2cdf7d243854189d7" name="NOTICE" role="doc" />
++   <file md5sum="efa40416571fc54aa59912203c0391e6" name="TODO" role="doc" />
++   <file md5sum="b7dd14328e218d3ecc97d85fb83d7ba7" name="TECHNOTES.txt" role="doc" />
++   <file md5sum="e7fdf1aa7be78296ac3baf23654b2792" name="apc.c" role="src" />
++   <file md5sum="09a525ff9a3850e6de42eee2adf07463" name="apc.dsp" role="src" />
++   <file md5sum="b82f7ac9d62387e674ce33a67afc7a3b" name="apc.h" role="src" />
++   <file md5sum="849d4591945e68babb4efb03e3d424ae" name="apc_bin.c" role="src" />
++   <file md5sum="dcaf89f1b2266c5c41a0ab19785bee7d" name="apc_bin.h" role="src" />
++   <file md5sum="8121a318b3008f743d8bed06dec9f729" name="apc_cache.c" role="src" />
++   <file md5sum="9b419e40230069357142c22eab50bc0a" name="apc_cache.h" role="src" />
++   <file md5sum="29385884afc3dbd6b3c85fe224e2a365" name="apc_compile.c" role="src" />
++   <file md5sum="12cb41077d90d258aa7eb59b834ef261" name="apc_compile.h" role="src" />
++   <file md5sum="c2f45f382269e062291f4a1972891a95" name="apc_debug.c" role="src" />
++   <file md5sum="46d182a6122f3c29a1904f62af7cfb51" name="apc_debug.h" role="src" />
++   <file md5sum="3bd799be126de9a5b701de001c9fdc8d" name="apc_fcntl.c" role="src" />
++   <file md5sum="396db63ae5ac6622826cdd6ea0a0f4e5" name="apc_fcntl.h" role="src" />
++   <file md5sum="d474fc330719125798f1cc8893418fea" name="apc_globals.h" role="src" />
++   <file md5sum="681d7c13200e8c63e06a72c29d0d83f5" name="apc_lock.h" role="src" />
++   <file md5sum="4c36bea0b58da92e574d3788a091cdcd" name="apc_main.c" role="src" />
++   <file md5sum="4ff2542ab8b12f8bce6d0c71f2a4ffb7" name="apc_main.h" role="src" />
++   <file md5sum="a1128f11e4db3dae87640595180c7e76" name="apc_mmap.c" role="src" />
++   <file md5sum="8a27408dbf63cf115d2845d73c1100c3" name="apc_mmap.h" role="src" />
++   <file md5sum="0226513b1cd48f3004f01ad2a24c7a90" name="apc_php.h" role="src" />
++   <file md5sum="247b2ed6b2c9f5064a9352a84a675034" name="apc_pthreadmutex.c" role="src" />
++   <file md5sum="ce3c8071287af9608a70a201bc149e42" name="apc_pthreadmutex.h" role="src" />
++   <file md5sum="8364571d83c9304ddd63bab54ef59f0e" name="apc_sem.c" role="src" />
++   <file md5sum="85d68fac7619e136c5dd2dba7498cebe" name="apc_sem.h" role="src" />
++   <file md5sum="874b69fe7572b47ca0c427213a24a004" name="apc_shm.c" role="src" />
++   <file md5sum="adcbe11cf10939218758cea6155571b5" name="apc_shm.h" role="src" />
++   <file md5sum="55788ceff1d153856173e9cb1be30af5" name="apc_sma.c" role="src" />
++   <file md5sum="7b915d4e05f034544794c0a22aca28df" name="apc_sma.h" role="src" />
++   <file md5sum="3651ead82ae249829bdfbd247845023a" name="apc_spin.c" role="src" />
++   <file md5sum="39b7125d52a30ad45f467f897a4f49fd" name="apc_spin.h" role="src" />
++   <file md5sum="bac2bf4975f8d178509c35687aacf264" name="apc_stack.c" role="src" />
++   <file md5sum="769e2610340545503843be5d27338bc0" name="apc_stack.h" role="src" />
++   <file md5sum="e06026d546096ccfd153f7ce282ec3d3" name="apc_zend.c" role="src" />
++   <file md5sum="d23c3716dc2be32d93583bdf2ee67fc5" name="apc_zend.h" role="src" />
++   <file md5sum="43c72ad19c9b3c2b7107ac38ac890b9c" name="apc_signal.c" role="src" />
++   <file md5sum="a93d49b7187c228033a0e6c906c660a9" name="apc_signal.h" role="src" />
++   <file md5sum="10bc3c48bf67d1f19d590d8aef62096f" name="apc_iterator.c" role="src" />
++   <file md5sum="fa2801d6755aca597222263a5c327c17" name="apc_iterator.h" role="src" />
++   <file md5sum="2985b114a6c62d4c645da54e15362133" name="apc_pool.c" role="src" />
++   <file md5sum="d33cf9a06d75796db5d2d6d05ce69cb2" name="apc_pool.h" role="src" />
++   <file md5sum="4825b1162664c350544045d54dc88e26" name="config.m4" role="src" />
++   <file md5sum="f8892e31c76167187d69df7870ad4510" name="config.w32" role="src" />
++   <file md5sum="36e70be4ad90d876f34743323da54a94" name="php_apc.c" role="src" />
++   <file md5sum="b6fdcec040076e3895b885a87ca6315c" name="php_apc.h" role="src" />
++   <file md5sum="5f6b362f9d82a1c71f19ad1516935b03" name="pgsql_s_lock.c" role="src" />
++   <file md5sum="a8fb99edbfe1118664ffceb868fc4756" name="pgsql_s_lock.h" role="src" />
++   <file md5sum="56e973e39dd83277cd2dc091115dd06d" name="apc_fcntl_win32.c" role="src" />
++   <file md5sum="71dc597b764f4e6ea12253d50e2167d5" name="apc_rfc1867.c" role="src" />
++   <file md5sum="6022f9c20f05b1ce3524c1bd5b87f8db" name="apc.php" role="php" />
++  </dir>
++ </contents>
++ <dependencies>
++  <required>
++   <php>
++    <min>5.1.0</min>
++   </php>
++   <pearinstaller>
++    <min>1.4.0</min>
++   </pearinstaller>
++  </required>
++ </dependencies>
++ <providesextension>apc</providesextension>
++ <extsrcrelease>
++  <configureoption default="no" name="enable-apc-filehits" prompt="Enable per request file info about files used from the APC cache" />
++  <configureoption default="no" name="enable-apc-spinlocks" prompt="Enable spin locks (EXPERIMENTAL)" />
++ </extsrcrelease>
++ <changelog>
++  <release>
++   <stability>
++    <release>stable</release>
++    <api>stable</api>
++   </stability>
++   <version>
++    <release>2.0.0</release>
++    <api>2.0.0</api>
++   </version>
++   <date>2003-07-01</date>
++   <notes>
++Complete rework.
++   </notes>
++  </release>
++  <release>
++   <stability>
++    <release>stable</release>
++    <api>stable</api>
 +   </stability>
 +   <version>
 +    <release>2.0.1</release>
 +    <api>2.0.0</api>
 +   </version>
 +   <date>2003-07-01</date>
-+   <notes>Win32 support added.</notes>
++   <notes>
++Win32 support added.
++   </notes>
 +  </release>
 +  <release>
 +   <stability>
@@ -12094,7 +14086,9 @@ diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
 +    <api>2.0.0</api>
 +   </version>
 +   <date>2004-03-12</date>
-+   <notes>Fixed non-existant class bug.</notes>
++   <notes>
++Fixed non-existant class bug.
++   </notes>
 +  </release>
 +  <release>
 +   <stability>
@@ -12106,7 +14100,9 @@ diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
 +    <api>3.0.0</api>
 +   </version>
 +   <date>2005-07-05</date>
-+   <notes>PHP-5.1 Support and numerous fixes</notes>
++   <notes>
++PHP-5.1 Support and numerous fixes
++   </notes>
 +  </release>
 +  <release>
 +   <stability>
@@ -12118,7 +14114,9 @@ diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
 +    <api>3.0.0</api>
 +   </version>
 +   <date>2005-07-05</date>
-+   <notes>PHP4 build fix</notes>
++   <notes>
++PHP4 build fix
++   </notes>
 +  </release>
 +  <release>
 +   <stability>
@@ -12130,7 +14128,9 @@ diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
 +    <api>3.0.0</api>
 +   </version>
 +   <date>2005-07-05</date>
-+   <notes>Default to mmap and add a better error message for shmget failures</notes>
++   <notes>
++Default to mmap and add a better error message for shmget failures
++   </notes>
 +  </release>
 +  <release>
 +   <stability>
@@ -12142,7 +14142,9 @@ diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
 +    <api>3.0.0</api>
 +   </version>
 +   <date>2005-07-07</date>
-+   <notes>Fix compile problem against PHP 5.0.x</notes>
++   <notes>
++Fix compile problem against PHP 5.0.x
++   </notes>
 +  </release>
 +  <release>
 +   <stability>
@@ -12154,9 +14156,11 @@ diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
 +    <api>3.0.0</api>
 +   </version>
 +   <date>2005-07-18</date>
-+   <notes>Add win32 support from Edin.
++   <notes>
++Add win32 support from Edin.
 +Add --with-apxs switch to work around problem when loading APC into Apache binary compiled with LFS switches
-+A couple of other minor fixes.</notes>
++A couple of other minor fixes.
++   </notes>
 +  </release>
 +  <release>
 +   <stability>
@@ -12168,10 +14172,12 @@ diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
 +    <api>3.0.0</api>
 +   </version>
 +   <date>2005-07-27</date>
-+   <notes>Make it easier for sapis that only populate file_handle-&gt;filename to use APC. (Rasmus)
++   <notes>
++Make it easier for sapis that only populate file_handle-&gt;filename to use APC. (Rasmus)
 +Support extensions such as bcompiler that need to hook into compile_file. (Val)
 +Ralf Becker&apos;s apcgui code has now become the default apc.php status page. (Ralf, Rasmus, Ilia)
-+Segfault in cache cleanup code (Ilia, Rasmus)</notes>
++Segfault in cache cleanup code (Ilia, Rasmus)
++   </notes>
 +  </release>
 +  <release>
 +   <stability>
@@ -12183,13 +14189,15 @@ diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
 +    <api>3.0.0</api>
 +   </version>
 +   <date>2005-07-30</date>
-+   <notes>Added apc.php to package.xml file.
++   <notes>
++Added apc.php to package.xml file.
 +Track per-entry memory usage. (Val)
 +Various apc.php fixes and enhancements. (Ralf, Ilia, Rasmus)
 +fcntl locking robustness fixes. (Rasmus)
 +Shared read-locks where possible. (Rasmus)
 +Added file_update_protection configuration parameter. (Rasmus)
-+Windows ZTS fixes (Frank)</notes>
++Windows ZTS fixes (Frank)
++   </notes>
 +  </release>
 +  <release>
 +   <stability>
@@ -12201,14 +14209,16 @@ diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
 +    <api>3.0.0</api>
 +   </version>
 +   <date>2005-08-16</date>
-+   <notes>Fix to apc.php to show final segment in frag chart. (Ilia)
++   <notes>
++Fix to apc.php to show final segment in frag chart. (Ilia)
 +A couple of win32 fixes. (Frank)
 +Add apc.enable_cli ini directive. (Rasmus)
 +Add test cases. (Marcus)
 +Fix apc_define_constants() bug - http://pecl.php.net/bugs/5084 (Rasmus)
 +Simplify user cache handling by removing the user_cache_stack (Rasmus)
 +Fix apc_fetch() memory corruption (Andrei,Rasmus)
-+Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)</notes>
++Added apc.max_file_size INI setting that allows exclusion of large files from being cached. Default file size limit, 1 megabyte. (Ilia)
++   </notes>
 +  </release>
 +  <release>
 +   <stability>
@@ -12220,8 +14230,10 @@ diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
 +    <api>3.0.0</api>
 +   </version>
 +   <date>2005-08-24</date>
-+   <notes>Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
-+Cache corruption fix in cache-full cleanup code (Gopal)</notes>
++   <notes>
++Fix invalid free in globals destructor introduced in 3.0.7 (Rasmus)
++Cache corruption fix in cache-full cleanup code (Gopal)
++   </notes>
 +  </release>
 +  <release>
 +   <stability>
@@ -12233,7 +14245,8 @@ diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
 +    <api>3.0.0</api>
 +   </version>
 +   <date>2006-03-04</date>
-+   <notes>Eliminate rand() call when slam_defense is not set (Rasmus)
++   <notes>
++Eliminate rand() call when slam_defense is not set (Rasmus)
 +Fix for __isset problem (Gopal)
 +Rewrite allocator from a &quot;best fit&quot; to a &quot;next fit&quot; algorithm (Rasmus)
 +Added a Cache Full counter so we have an idea how many times the segment has filled up causing an expunge (Rasmus)
@@ -12249,7 +14262,8 @@ diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
 +Add a lock cleanup safety net to request shutdown (Rasmus)
 +Fix apc.slam_defense edge-case bug (Rasmus)
 +User entry memory usage tracking support (Ilia)
-+Allow keys used in apc_store/apc_fetch/apc_delete to be binary safe and prevent conflicts between keys that are found at the start of other keys. (Ilia)</notes>
++Allow keys used in apc_store/apc_fetch/apc_delete to be binary safe and prevent conflicts between keys that are found at the start of other keys. (Ilia)
++   </notes>
 +  </release>
 +  <release>
 +   <stability>
@@ -12261,3020 +14275,5048 @@ diff -ubrN php-5.2.5-orig/ext/apc/package.xml php-5.2.5/ext/apc/package.xml
 +    <api>3.0.0</api>
 +   </version>
 +   <date>2006-03-11</date>
-+   <notes>* Add apc.stat ini flag which defaults to 1.  If set to 0, the main script and any fullpath
++   <notes>
++* Add apc.stat ini flag which defaults to 1.  If set to 0, the main script and any fullpath
 +  includes will not be stat&apos;ed for any changes.  You will have to restart the server if you
 +  change anything.  This mode increases performance quite a bit, especially if you have a
 +  lot of includes.
 +
-+* Get rid of the lock safety net hack I added in 3.0.9.  It seems to cause more problems
-+  than it solves.  I&apos;ll need to revisit locking and signal handling at some point soon.</notes>
-+  </release>
-+  <release>
-+   <stability>
-+    <release>stable</release>
-+    <api>stable</api>
-+   </stability>
-+   <version>
-+    <release>3.0.11</release>
-+    <api>3.0.0</api>
-+   </version>
-+   <date>2006-08-16</date>
-+   <notes>* Made --enable-apc-mmap the default compile option (for real this time)
++* Get rid of the lock safety net hack I added in 3.0.9.  It seems to cause more problems
++  than it solves.  I&apos;ll need to revisit locking and signal handling at some point soon.
++   </notes>
++  </release>
++  <release>
++   <stability>
++    <release>stable</release>
++    <api>stable</api>
++   </stability>
++   <version>
++    <release>3.0.11</release>
++    <api>3.0.0</api>
++   </version>
++   <date>2006-08-16</date>
++   <notes>
++* Made --enable-apc-mmap the default compile option (for real this time)
++
++* Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
++  only fetch header information to make it useful when you have tens of
++  thousands of entries.  (Brian Shire)
++
++* 64-bit fixes (George)
++
++* Don&apos;t mix Full Path and Inode keys (George)
++
++* Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
++  require_once() and include_once() statements. (Sara)
++
++* Add a non-blocking write_lock for cache inserts.  This is a better approach
++  to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
++
++* A bit of work on the optimizer.  (Sara)
++
++* Various memory issues resolved. (Gopal)
++   </notes>
++  </release>
++  <release>
++   <stability>
++    <release>stable</release>
++    <api>stable</api>
++   </stability>
++   <version>
++    <release>3.0.12</release>
++    <api>3.0.0</api>
++   </version>
++   <date>2006-09-04</date>
++   <notes>
++* Fix stray debug message
++
++* Work on the optimizer - still not stable (Gopal, Ilia, Sara)
++
++* Performance boost - Replace multiple loops over the opcode
++  array with a single loop for copying, jump fixups and auto
++  global pre-fetches. (Gopal)
++
++* Perform fetch_global checks only in php5 and only if 
++  auto_globals_jit is enabled. (Gopal)
++
++* Fix bug #8579 - scrub php4 classes&apos; function_table and default
++  properties before inserting into cache. (Gopal)
++
++* Fix bug #8606 - ZEND_FETCH_GLOBAL is not an opcode, but is a 
++  op1-&gt;type.  The opcodes applicable are ZEND_FETCH_R and 
++  ZEND_FETCH_W. (Gopal)
++
++* PHP 5.2 Compatibility (Gopal)
++
++* Make the include_once override optional - default off (Sara)
++
++* Fixed crash when apc run in CLI, but enable_cli is off. (Ilia)
++
++* Ensure that the apc_globals-&gt;cache_stack is cleared before the 
++  shm cache is destroyed. Fixes segfault for corner-case i.e request
++  shutdown (apc_deactivate) is not called before module shutdown 
++  calls (php_apc_shutdown_globals)  (Gopal)
++
++* TSRM fixes (ensure ts_free_id before apc.so is dlclosed) (Gopal)
++
++* Fix memory leak of apc_cache_info_t-&gt;deleted_list (Gopal)
++   </notes>
++  </release>
++  <release>
++   <stability>
++    <release>stable</release>
++    <api>stable</api>
++   </stability>
++   <version>
++    <release>3.0.12p1</release>
++    <api>3.0.0</api>
++   </version>
++   <date>2006-09-05</date>
++   <notes>
++* The only change here is a trivial PHP 4 build fix.
++   </notes>
++  </release>
++  <release>
++   <stability>
++    <release>stable</release>
++    <api>stable</api>
++   </stability>
++   <version>
++    <release>3.0.12p2</release>
++    <api>3.0.0</api>
++   </version>
++   <date>2006-09-05</date>
++   <notes>
++* Let&apos;s get the version number right.  3.0.12p2 now.
++   </notes>
++  </release>
++  <release>
++   <stability>
++    <release>stable</release>
++    <api>stable</api>
++   </stability>
++   <version>
++    <release>3.0.13</release>
++    <api>3.0.0</api>
++   </version>
++   <date>2007-02-24</date>
++   <notes>
++* PHP 5.2 file upload progress tracking support (Rasmus)
++* Pthread mutex and spin locks (Shire)
++* Recursive zval support for apc_fetch/_store (Shire, Gopal)
++* apc.stat_ctime flag for ctime checks (Rasmus)
++* Multiple key fetches with apc_fetch (Shire)
++* Canary checks for shm memory deallocation (Gopal)
++* Add hooks for external optimizer (Shire)
++* Obsolete and remove apc optimizer (Gopal)
++* APC info changes - cache insert rate, hit and miss rates (Shire)
++* Fix apc_load_constants (Gopal)
++* Rewrite dump opcode code to use vld (Gopal)
++* Use apc_[ewn]print functions for error reporting (Shire) 
++* Auto global fixes and refactoring (Gopal, Shire)
++* Fix memory leaks in object serialization (Ilia)
++* Memory cleanup code for destructor order (Gopal)
++* Win32 build fixes (Ilia, Wez)
++* ZTS and Php 4 build fixes (Bjori)
++* Add apc_add() function (Rasmus)
++* Add optional limited flag to apc_sma_info() (Rasmus)
++   </notes>
++  </release>
++  <release>
++   <stability>
++    <release>stable</release>
++    <api>stable</api>
++   </stability>
++   <version>
++    <release>3.0.14</release>
++    <api>3.0.0</api>
++   </version>
++   <date>2007-04-02</date>
++   <notes>
++* Build fix (Shire)
++* Don&apos;t hook the upload hook if APC is disabled (Rasmus)
++* Local shadow cache support (Gopal)
++* Avoid uneccessary loops over op_arrays for &quot;known&quot; auto-globals (Gopal)
++* Fix apc_add() to overwrite timed out user entries (Rasmus)
++* Fix double inclusion of files with conditional classes in php4 (Gopal)
++* Allocator fixes to reduce fragmentation (Gopal)
++   </notes>
++  </release>
++  <release>
++   <stability>
++    <release>stable</release>
++    <api>stable</api>
++   </stability>
++   <version>
++    <release>3.0.15</release>
++    <api>3.0.0</api>
++   </version>
++   <date>2007-10-18</date>
++   <notes>
++* Eliminate a per-request time() syscall (Rasmus)
++* Added rfc1867 prefix, name, and freq ini options (Shire)
++* Allow deletion of individual user cache entries via apc.php (Sara)
++* Fix overzealous cleanup during RSHUTDOWN (Gopal)
++* Fix memory alignment and locking issues (Gopal)
++* Make apc_compile insert/replace entries (Shire)
++* Make mixed inheritance recompile &amp; cache afresh  (Gopal)
++* Make nostat mode search include_path for canonicalization (Gopal)
++* ZTS &amp; other compile fixes (Gopal, Edin, Shire)
++   </notes>
++  </release>
++  <release>
++   <version>
++    <release>3.0.16</release>
++    <api>3.0.0</api>
++   </version>
++   <stability>
++    <release>stable</release>
++    <api>stable</api>
++   </stability>
++   <license uri="http://www.php.net/license">PHP License</license>
++   <date>2008-03-26</date>
++   <notes>
++* Fix for longstanding cache-full crash (Christian Seiler)
++  http://news.php.net/php.pecl.dev/4951 for the details
++* Added optional shm unmap on a fatal signal feature (Lucas Nealan)
++* Added PTHREAD_MUTEX_ADAPTIVE_NP option pthread locks (Paul Saab)
++* Minor cleanups (Lucas Nealan)
++* Added configure option to enable apc_cache_info(&apos;filehits&apos;) (Shire)
++   </notes>
++  </release>
++  <release>
++   <version>
++    <release>3.0.17</release>
++    <api>3.0.0</api>
++   </version>
++   <stability>
++    <release>stable</release>
++    <api>stable</api>
++   </stability>
++   <license uri="http://www.php.net/license">PHP License</license>
++   <date>2008-03-29</date>
++   <notes>
++* Crash fixes
++* Fix apc_add() cache expunge bug (Rasmus)
++* Added parameter to apc_fetch to determine success/failure when fetching booleans (shire)
++* Fix misc. memleaks (shire)
++   </notes>
++  </release>
++  <release>
++   <version>
++    <release>3.0.18</release>
++    <api>3.0.0</api>
++   </version>
++   <stability>
++    <release>stable</release>
++    <api>stable</api>
++   </stability>
++   <license uri="http://www.php.net/license">PHP License</license>
++   <date>2008-03-29</date>
++   <notes>
++- Revert apc_expunge_cb bug-fix
++- Misc memleaks
++   </notes>
++  </release>
++  <release>
++   <version>
++    <release>3.0.19</release>
++    <api>3.0.0</api>
++   </version>
++   <stability>
++    <release>stable</release>
++    <api>stable</api>
++   </stability>
++   <license uri="http://www.php.net/license">PHP License</license>
++   <date>2008-05-15</date>
++   <notes>
++- Safe-mode and fast-cgi fixes
++- Fix double-free of builtin_functions
++- php 5.3 fixes
++   </notes>
++  </release>
++  <release>
++   <version>
++    <release>3.1.1</release>
++    <api>3.1.0</api>
++   </version>
++   <stability>
++    <release>beta</release>
++    <api>beta</api>
++   </stability>
++   <license uri="http://www.php.net/license">PHP License</license>
++   <date>2008-12-12</date>
++   <notes>
++- PHP4 compatibilty break
++- apc_pool allocator (Gopal) 
++- doubly-linked sma allocator (Shire)
++- php 5.3 gc compatibility (Gopal)
++- APCIterator for easy access (Shire)
++- apc_delete_file (Shire)
++- apc_inc/apc_dec/apc_cas functions (Shire)
++- apc.canonicalize (Gopal)
++- apc.preload_path (Gopal)
++- apc.rfc1867_ttl  (Shire)
++- apc.file_md5     (Shire)
++- consolidate locking macros (Shire)
++- remove futex/TSRM locks  (Shire)
++- non-blocking semaphore locks  (Shire)
++- zval* object rework (Gopal)
++   </notes>
++  </release>
++  <release>
++   <version>
++    <release>3.1.2</release>
++    <api>3.1.0</api>
++   </version>
++   <stability>
++    <release>beta</release>
++    <api>beta</api>
++   </stability>
++   <license uri="http://www.php.net/license">PHP License</license>
++   <date>2008-12-12</date>
++   <notes>
++- pecl package.xml/build fixes (bjori)
++   </notes>
++  </release>
++  <release>
++   <version>
++    <release>3.1.3</release>
++    <api>3.1.0</api>
++   </version>
++   <stability>
++    <release>beta</release>
++    <api>beta</api>
++   </stability>
++   <license uri="http://www.php.net/license">PHP License</license>
++   <date>2009-08-13</date>
++   <notes>
++- pecl package.xml/build fixes (bjori)
++- 5.3 support + test-cases (Gopal)
++- Lazy loading support (Shire)
++- Fix PCRE module init order issues (Shire)
++- APCIterator fixes (Shire)
++- Cache slam checks (Gopal)
++- ZEND_JMP_SET support (Shire)
++- apc.use_request_time option (shire)
++- apc.php hostname fixes (Shire)
++- memprotect framework (Gopal)
++- Win32 build-fixes (Kalle)
++   </notes>
++  </release>
++ </changelog>
++</package>
+diff -Naur php-5.3.1.orig/ext/apc/pgsql_s_lock.c php-5.3.1/ext/apc/pgsql_s_lock.c
+--- php-5.3.1.orig/ext/apc/pgsql_s_lock.c      1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/pgsql_s_lock.c   1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,485 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2007-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | The following code was ported from the PostgreSQL project, please    |
++  |  see appropriate copyright notices that follow.                      |
++  | Initial conversion by Brian Shire <shire@php.net>                    |
++  +----------------------------------------------------------------------+
++
++ */
++
++/* $Id: pgsql_s_lock.c 284592 2009-07-22 10:53:50Z kalle $ */
++
++/*-------------------------------------------------------------------------
++ *
++ * s_lock.c
++ *       Hardware-dependent implementation of spinlocks.
++ *
++ *
++ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
++ * Portions Copyright (c) 1994, Regents of the University of California
++ *
++ *
++ * IDENTIFICATION
++ *      $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.47 2006/10/04 00:29:58 momjian Exp $
++ *
++ *-------------------------------------------------------------------------
++ */
++/* #include "postgres.h"  -- Removed for APC */
++
++/* -- Added for APC -- */
++#include "apc.h"
++#ifdef APC_SPIN_LOCKS
++
++#ifdef S_LOCK_TEST
++#include <stdio.h>
++#endif
++#ifndef WIN32
++#include <sys/select.h>
++#endif
++/* ---- */
++
++#include <time.h>
++#ifdef WIN32
++#include "win32/unistd.h"
++#else
++#include <unistd.h>
++#endif
++
++/* #include "storage/s_lock.h" -- Removed for APC */
++#include "pgsql_s_lock.h"
++
++static int    spins_per_delay = DEFAULT_SPINS_PER_DELAY;
++
++
++/* -- APC specific additions ------------------------------*/
++/* The following dependencies have been copied from 
++ * other pgsql source files.  The original locations 
++ * have been noted.
++ */
++
++/* -- from include/c.h -- */
++#ifndef TRUE
++#define TRUE  1
++#endif
++
++#ifndef FALSE
++#define FALSE 0
++#endif
++
++/* -- from include/pg_config_manual.h -- */
++#define MAX_RANDOM_VALUE (0x7FFFFFFF) 
++
++/*
++ * Max
++ *    Return the maximum of two numbers.
++ */
++#define Max(x, y)   ((x) > (y) ? (x) : (y))
++
++/* -- from include/c.h -- */
++/*
++ * Min
++ *    Return the minimum of two numbers.
++ */
++#define Min(x, y)   ((x) < (y) ? (x) : (y))
++
++
++/* -- from backend/port/win32/signal.c -- */
++/*
++ * pg_usleep --- delay the specified number of microseconds.
++ *
++ * NOTE: although the delay is specified in microseconds, the effective
++ * resolution is only 1/HZ, or 10 milliseconds, on most Unixen.  Expect
++ * the requested delay to be rounded up to the next resolution boundary.
++ *
++ * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
++ */
++void
++pg_usleep(long microsec)
++{
++      if (microsec > 0)
++      {
++#ifndef WIN32
++              struct timeval delay;
++
++              delay.tv_sec = microsec / 1000000L;
++              delay.tv_usec = microsec % 1000000L;
++              (void) select(0, NULL, NULL, NULL, &delay);
++#else
++              SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
++#endif
++      }
++}
++
++/* -- End APC specific additions ------------------------------*/
++
++
++/*
++ * s_lock_stuck() - complain about a stuck spinlock
++ */
++static void
++s_lock_stuck(volatile slock_t *lock, const char *file, int line)
++{
++#if defined(S_LOCK_TEST)
++      fprintf(stderr,
++                      "\nStuck spinlock (%p) detected at %s:%d.\n",
++                      lock, file, line);
++      exit(1);
++#else
++  /* -- Removed for APC
++      elog(PANIC, "stuck spinlock (%p) detected at %s:%d",
++               lock, file, line);
++  */
++  apc_eprint("Stuck spinlock (%p) detected", lock);
++#endif
++}
++
++
++/*
++ * s_lock(lock) - platform-independent portion of waiting for a spinlock.
++ */
++void
++s_lock(volatile slock_t *lock, const char *file, int line)
++{
++      /*
++       * We loop tightly for awhile, then delay using pg_usleep() and try again.
++       * Preferably, "awhile" should be a small multiple of the maximum time we
++       * expect a spinlock to be held.  100 iterations seems about right as an
++       * initial guess.  However, on a uniprocessor the loop is a waste of
++       * cycles, while in a multi-CPU scenario it's usually better to spin a bit
++       * longer than to call the kernel, so we try to adapt the spin loop count
++       * depending on whether we seem to be in a uniprocessor or multiprocessor.
++       *
++       * Note: you might think MIN_SPINS_PER_DELAY should be just 1, but you'd
++       * be wrong; there are platforms where that can result in a "stuck
++       * spinlock" failure.  This has been seen particularly on Alphas; it seems
++       * that the first TAS after returning from kernel space will always fail
++       * on that hardware.
++       *
++       * Once we do decide to block, we use randomly increasing pg_usleep()
++       * delays. The first delay is 1 msec, then the delay randomly increases to
++       * about one second, after which we reset to 1 msec and start again.  The
++       * idea here is that in the presence of heavy contention we need to
++       * increase the delay, else the spinlock holder may never get to run and
++       * release the lock.  (Consider situation where spinlock holder has been
++       * nice'd down in priority by the scheduler --- it will not get scheduled
++       * until all would-be acquirers are sleeping, so if we always use a 1-msec
++       * sleep, there is a real possibility of starvation.)  But we can't just
++       * clamp the delay to an upper bound, else it would take a long time to
++       * make a reasonable number of tries.
++       *
++       * We time out and declare error after NUM_DELAYS delays (thus, exactly
++       * that many tries).  With the given settings, this will usually take 2 or
++       * so minutes.  It seems better to fix the total number of tries (and thus
++       * the probability of unintended failure) than to fix the total time
++       * spent.
++       *
++       * The pg_usleep() delays are measured in milliseconds because 1 msec is a
++       * common resolution limit at the OS level for newer platforms. On older
++       * platforms the resolution limit is usually 10 msec, in which case the
++       * total delay before timeout will be a bit more.
++       */
++#define MIN_SPINS_PER_DELAY 10
++#define MAX_SPINS_PER_DELAY 1000
++#define NUM_DELAYS                    1000
++#define MIN_DELAY_MSEC                1
++#define MAX_DELAY_MSEC                1000
++
++      int                     spins = 0;
++      int                     delays = 0;
++      int                     cur_delay = 0;
++  
++      while (TAS(lock))
++      {
++              /* CPU-specific delay each time through the loop */
++              SPIN_DELAY();
++
++              /* Block the process every spins_per_delay tries */
++              if (++spins >= spins_per_delay)
++              {
++                      if (++delays > NUM_DELAYS)
++                              s_lock_stuck(lock, file, line);
++
++                      if (cur_delay == 0) /* first time to delay? */
++                              cur_delay = MIN_DELAY_MSEC;
++
++                      pg_usleep(cur_delay * 1000L);
++
++#if defined(S_LOCK_TEST)
++                      fprintf(stdout, "*");
++                      fflush(stdout);
++#endif
++
++                      /* increase delay by a random fraction between 1X and 2X */
++                      cur_delay += (int) (cur_delay *
++                                        ((double) rand() / (double) MAX_RANDOM_VALUE) + 0.5);
++                      /* wrap back to minimum delay when max is exceeded */
++                      if (cur_delay > MAX_DELAY_MSEC)
++                              cur_delay = MIN_DELAY_MSEC;
++
++                      spins = 0;
++              }
++      }
++
++      /*
++       * If we were able to acquire the lock without delaying, it's a good
++       * indication we are in a multiprocessor.  If we had to delay, it's a sign
++       * (but not a sure thing) that we are in a uniprocessor. Hence, we
++       * decrement spins_per_delay slowly when we had to delay, and increase it
++       * rapidly when we didn't.  It's expected that spins_per_delay will
++       * converge to the minimum value on a uniprocessor and to the maximum
++       * value on a multiprocessor.
++       *
++       * Note: spins_per_delay is local within our current process. We want to
++       * average these observations across multiple backends, since it's
++       * relatively rare for this function to even get entered, and so a single
++       * backend might not live long enough to converge on a good value.      That
++       * is handled by the two routines below.
++       */
++      if (cur_delay == 0)
++      {
++              /* we never had to delay */
++              if (spins_per_delay < MAX_SPINS_PER_DELAY)
++                      spins_per_delay = Min(spins_per_delay + 100, MAX_SPINS_PER_DELAY);
++      }
++      else
++      {
++              if (spins_per_delay > MIN_SPINS_PER_DELAY)
++                      spins_per_delay = Max(spins_per_delay - 1, MIN_SPINS_PER_DELAY);
++      }
++}
++
++
++#if 0  /* -- APC doesn't use the set_spins_per_delay or update_spins_per_delay -- */
++/*
++ * Set local copy of spins_per_delay during backend startup.
++ *
++ * NB: this has to be pretty fast as it is called while holding a spinlock
++ */
++void
++set_spins_per_delay(int shared_spins_per_delay)
++{
++      spins_per_delay = shared_spins_per_delay;
++}
++
++/*
++ * Update shared estimate of spins_per_delay during backend exit.
++ *
++ * NB: this has to be pretty fast as it is called while holding a spinlock
++ */
++int
++update_spins_per_delay(int shared_spins_per_delay)
++{
++      /*
++       * We use an exponential moving average with a relatively slow adaption
++       * rate, so that noise in any one backend's result won't affect the shared
++       * value too much.      As long as both inputs are within the allowed range,
++       * the result must be too, so we need not worry about clamping the result.
++       *
++       * We deliberately truncate rather than rounding; this is so that single
++       * adjustments inside a backend can affect the shared estimate (see the
++       * asymmetric adjustment rules above).
++       */
++      return (shared_spins_per_delay * 15 + spins_per_delay) / 16;
++}
++#endif
++
++/*
++ * Various TAS implementations that cannot live in s_lock.h as no inline
++ * definition exists (yet).
++ * In the future, get rid of tas.[cso] and fold it into this file.
++ *
++ * If you change something here, you will likely need to modify s_lock.h too,
++ * because the definitions for these are split between this file and s_lock.h.
++ */
++
++
++#ifdef HAVE_SPINLOCKS                 /* skip spinlocks if requested */
++
++
++#if defined(__GNUC__)
++
++/*
++ * All the gcc flavors that are not inlined
++ */
++
++
++/*
++ * Note: all the if-tests here probably ought to be testing gcc version
++ * rather than platform, but I don't have adequate info to know what to
++ * write.  Ideally we'd flush all this in favor of the inline version.
++ */
++#if defined(__m68k__) && !defined(__linux__)
++/* really means: extern int tas(slock_t* **lock); */
++static void
++tas_dummy()
++{
++      __asm__         __volatile__(
++#if defined(__NetBSD__) && defined(__ELF__)
++/* no underscore for label and % for registers */
++                                                                               "\
++.global               tas                             \n\
++tas:                                                  \n\
++                      movel   %sp@(0x4),%a0   \n\
++                      tas     %a0@            \n\
++                      beq     _success        \n\
++                      moveq   #-128,%d0       \n\
++                      rts                             \n\
++_success:                                             \n\
++                      moveq   #0,%d0          \n\
++                      rts                             \n"
++#else
++                                                                               "\
++.global               _tas                            \n\
++_tas:                                                 \n\
++                      movel   sp@(0x4),a0     \n\
++                      tas     a0@                     \n\
++                      beq     _success        \n\
++                      moveq   #-128,d0        \n\
++                      rts                                     \n\
++_success:                                             \n\
++                      moveq   #0,d0           \n\
++                      rts                                     \n"
++#endif   /* __NetBSD__ && __ELF__ */
++      );
++}
++#endif   /* __m68k__ && !__linux__ */
++#else                                                 /* not __GNUC__ */
++
++/*
++ * All non gcc
++ */
++
++
++#if defined(sun3)
++static void
++tas_dummy()                                           /* really means: extern int tas(slock_t
++                                                               * *lock); */
++{
++      asm("LLA0:");
++      asm("   .data");
++      asm("   .text");
++      asm("|#PROC# 04");
++      asm("   .globl  _tas");
++      asm("_tas:");
++      asm("|#PROLOGUE# 1");
++      asm("   movel   sp@(0x4),a0");
++      asm("   tas a0@");
++      asm("   beq LLA1");
++      asm("   moveq   #-128,d0");
++      asm("   rts");
++      asm("LLA1:");
++      asm("   moveq   #0,d0");
++      asm("   rts");
++      asm("   .data");
++}
++#endif   /* sun3 */
++#endif   /* not __GNUC__ */
++#endif   /* HAVE_SPINLOCKS */
++
++
++
++/*****************************************************************************/
++#if defined(S_LOCK_TEST)
++
++/*
++ * test program for verifying a port's spinlock support.
++ */
++
++struct test_lock_struct
++{
++      char            pad1;
++      slock_t         lock;
++      char            pad2;
++};
++
++volatile struct test_lock_struct test_lock;
++
++int
++main()
++{
++      srandom((unsigned int) time(NULL));
++
++      test_lock.pad1 = test_lock.pad2 = 0x44;
++
++      S_INIT_LOCK(&test_lock.lock);
++
++      if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
++      {
++              printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
++              return 1;
++      }
++
++      if (!S_LOCK_FREE(&test_lock.lock))
++      {
++              printf("S_LOCK_TEST: failed, lock not initialized\n");
++              return 1;
++      }
++
++      S_LOCK(&test_lock.lock);
++
++      if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
++      {
++              printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
++              return 1;
++      }
++
++      if (S_LOCK_FREE(&test_lock.lock))
++      {
++              printf("S_LOCK_TEST: failed, lock not locked\n");
++              return 1;
++      }
++
++      S_UNLOCK(&test_lock.lock);
++
++      if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
++      {
++              printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
++              return 1;
++      }
++
++      if (!S_LOCK_FREE(&test_lock.lock))
++      {
++              printf("S_LOCK_TEST: failed, lock not unlocked\n");
++              return 1;
++      }
++
++      S_LOCK(&test_lock.lock);
++
++      if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
++      {
++              printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
++              return 1;
++      }
++
++      if (S_LOCK_FREE(&test_lock.lock))
++      {
++              printf("S_LOCK_TEST: failed, lock not re-locked\n");
++              return 1;
++      }
++
++      printf("S_LOCK_TEST: this will print %d stars and then\n", NUM_DELAYS);
++      printf("             exit with a 'stuck spinlock' message\n");
++      printf("             if S_LOCK() and TAS() are working.\n");
++      fflush(stdout);
++
++      s_lock(&test_lock.lock, __FILE__, __LINE__);
++
++      printf("S_LOCK_TEST: failed, lock not locked\n");
++      return 1;
++}
++
++#endif   /* S_LOCK_TEST */
++
++#endif /* APC_SPIN_LOCKS */
+diff -Naur php-5.3.1.orig/ext/apc/pgsql_s_lock.h php-5.3.1/ext/apc/pgsql_s_lock.h
+--- php-5.3.1.orig/ext/apc/pgsql_s_lock.h      1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/pgsql_s_lock.h   1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,928 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2007-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | The following code was ported from the PostgreSQL project, please    |
++  |  see appropriate copyright notices that follow.                      |
++  | Initial conversion by Brian Shire <shire@php.net>                    |
++  +----------------------------------------------------------------------+
++
++ */
++
++/* $Id: pgsql_s_lock.h 268255 2008-11-04 05:42:11Z rasmus $ */
++
++/*-------------------------------------------------------------------------
++ *
++ * s_lock.h
++ *       Hardware-dependent implementation of spinlocks.
++ *
++ *    NOTE: none of the macros in this file are intended to be called directly.
++ *    Call them through the hardware-independent macros in spin.h.
++ *
++ *    The following hardware-dependent macros must be provided for each
++ *    supported platform:
++ *
++ *    void S_INIT_LOCK(slock_t *lock)
++ *            Initialize a spinlock (to the unlocked state).
++ *
++ *    void S_LOCK(slock_t *lock)
++ *            Acquire a spinlock, waiting if necessary.
++ *            Time out and abort() if unable to acquire the lock in a
++ *            "reasonable" amount of time --- typically ~ 1 minute.
++ *
++ *    void S_UNLOCK(slock_t *lock)
++ *            Unlock a previously acquired lock.
++ *
++ *    bool S_LOCK_FREE(slock_t *lock)
++ *            Tests if the lock is free. Returns TRUE if free, FALSE if locked.
++ *            This does *not* change the state of the lock.
++ *
++ *    void SPIN_DELAY(void)
++ *            Delay operation to occur inside spinlock wait loop.
++ *
++ *    Note to implementors: there are default implementations for all these
++ *    macros at the bottom of the file.  Check if your platform can use
++ *    these or needs to override them.
++ *
++ *  Usually, S_LOCK() is implemented in terms of an even lower-level macro
++ *    TAS():
++ *
++ *    int TAS(slock_t *lock)
++ *            Atomic test-and-set instruction.  Attempt to acquire the lock,
++ *            but do *not* wait.      Returns 0 if successful, nonzero if unable
++ *            to acquire the lock.
++ *
++ *    TAS() is NOT part of the API, and should never be called directly.
++ *
++ *    CAUTION: on some platforms TAS() may sometimes report failure to acquire
++ *    a lock even when the lock is not locked.  For example, on Alpha TAS()
++ *    will "fail" if interrupted.  Therefore TAS() should always be invoked
++ *    in a retry loop, even if you are certain the lock is free.
++ *
++ *    ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence
++ *    points, ie, loads and stores of other values must not be moved across
++ *    a lock or unlock.  In most cases it suffices to make the operation be
++ *    done through a "volatile" pointer.
++ *
++ *    On most supported platforms, TAS() uses a tas() function written
++ *    in assembly language to execute a hardware atomic-test-and-set
++ *    instruction.  Equivalent OS-supplied mutex routines could be used too.
++ *
++ *    If no system-specific TAS() is available (ie, HAVE_SPINLOCKS is not
++ *    defined), then we fall back on an emulation that uses SysV semaphores
++ *    (see spin.c).  This emulation will be MUCH MUCH slower than a proper TAS()
++ *    implementation, because of the cost of a kernel call per lock or unlock.
++ *    An old report is that Postgres spends around 40% of its time in semop(2)
++ *    when using the SysV semaphore code.
++ *
++ *
++ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
++ * Portions Copyright (c) 1994, Regents of the University of California
++ *
++ *      $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.157 2006/06/07 22:24:45 momjian Exp $
++ *
++ *-------------------------------------------------------------------------
++ */
++#ifndef S_LOCK_H
++#define S_LOCK_H
++
++/** APC namespace protection ************************************************/
++/* hack to protect against any possible runtime namespace collisions...*/
++#define pg_usleep               apc_spin_pg_usleep
++#define s_lock                  apc_spin_s_lock
++#define spins_per_delay         apc_spin_spins_per_delay
++/****************************************************************************/
 +
-+* Add an optional flag to apc_cache_info() and some apc.php tweaks to make it
-+  only fetch header information to make it useful when you have tens of
-+  thousands of entries.  (Brian Shire)
 +
-+* 64-bit fixes (George)
++/* #include "storage/pg_sema.h"   -- Removed for APC */
 +
-+* Don&apos;t mix Full Path and Inode keys (George)
++#define HAVE_SPINLOCKS 1 /* -- Added for APC */
 +
-+* Override ZEND_INCLUDE_OR_EVAL opcode (when possible) to speed up use of
-+  require_once() and include_once() statements. (Sara)
++#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
 +
-+* Add a non-blocking write_lock for cache inserts.  This is a better approach
-+  to prevent cache slams and deprecates the slam_defense setting. (Rasmus)
 +
-+* A bit of work on the optimizer.  (Sara)
++#if defined(__GNUC__) || defined(__ICC)
++/*************************************************************************
++ * All the gcc inlines
++ * Gcc consistently defines the CPU as __cpu__.
++ * Other compilers use __cpu or __cpu__ so we test for both in those cases.
++ */
 +
-+* Various memory issues resolved. (Gopal)</notes>
-+  </release>
-+  <release>
-+   <stability>
-+    <release>stable</release>
-+    <api>stable</api>
-+   </stability>
-+   <version>
-+    <release>3.0.12</release>
-+    <api>3.0.0</api>
-+   </version>
-+   <date>2006-09-04</date>
-+   <notes>* Fix stray debug message
++/*----------
++ * Standard gcc asm format (assuming "volatile slock_t *lock"):
 +
-+* Work on the optimizer - still not stable (Gopal, Ilia, Sara)
++      __asm__ __volatile__(
++              "       instruction     \n"
++              "       instruction     \n"
++              "       instruction     \n"
++:             "=r"(_res), "+m"(*lock)         // return register, in/out lock value
++:             "r"(lock)                                       // lock pointer, in input register
++:             "memory", "cc");                        // show clobbered registers here
 +
-+* Performance boost - Replace multiple loops over the opcode
-+  array with a single loop for copying, jump fixups and auto
-+  global pre-fetches. (Gopal)
++ * The output-operands list (after first colon) should always include
++ * "+m"(*lock), whether or not the asm code actually refers to this
++ * operand directly.  This ensures that gcc believes the value in the
++ * lock variable is used and set by the asm code.  Also, the clobbers
++ * list (after third colon) should always include "memory"; this prevents
++ * gcc from thinking it can cache the values of shared-memory fields
++ * across the asm code.  Add "cc" if your asm code changes the condition
++ * code register, and also list any temp registers the code uses.
++ *----------
++ */
 +
-+* Perform fetch_global checks only in php5 and only if 
-+  auto_globals_jit is enabled. (Gopal)
 +
-+* Fix bug #8579 - scrub php4 classes&apos; function_table and default
-+  properties before inserting into cache. (Gopal)
++#ifdef __i386__               /* 32-bit i386 */
++#define HAS_TEST_AND_SET
++
++typedef unsigned char slock_t;
++
++#define TAS(lock) tas(lock)
++
++static __inline__ int
++tas(volatile slock_t *lock)
++{
++      register slock_t _res = 1;
++
++      /*
++       * Use a non-locking test before asserting the bus lock.  Note that the
++       * extra test appears to be a small loss on some x86 platforms and a small
++       * win on others; it's by no means clear that we should keep it.
++       */
++      __asm__ __volatile__(
++              "       cmpb    $0,%1   \n"
++              "       jne             1f              \n"
++              "       lock                    \n"
++              "       xchgb   %0,%1   \n"
++              "1: \n"
++:             "+q"(_res), "+m"(*lock)
++:
++:             "memory", "cc");
++      return (int) _res;
++}
++
++#define SPIN_DELAY() spin_delay()
++
++static __inline__ void
++spin_delay(void)
++{
++      /*
++       * This sequence is equivalent to the PAUSE instruction ("rep" is
++       * ignored by old IA32 processors if the following instruction is
++       * not a string operation); the IA-32 Architecture Software
++       * Developer's Manual, Vol. 3, Section 7.7.2 describes why using
++       * PAUSE in the inner loop of a spin lock is necessary for good
++       * performance:
++       *
++       *     The PAUSE instruction improves the performance of IA-32
++       *     processors supporting Hyper-Threading Technology when
++       *     executing spin-wait loops and other routines where one
++       *     thread is accessing a shared lock or semaphore in a tight
++       *     polling loop. When executing a spin-wait loop, the
++       *     processor can suffer a severe performance penalty when
++       *     exiting the loop because it detects a possible memory order
++       *     violation and flushes the core processor's pipeline. The
++       *     PAUSE instruction provides a hint to the processor that the
++       *     code sequence is a spin-wait loop. The processor uses this
++       *     hint to avoid the memory order violation and prevent the
++       *     pipeline flush. In addition, the PAUSE instruction
++       *     de-pipelines the spin-wait loop to prevent it from
++       *     consuming execution resources excessively.
++       */
++      __asm__ __volatile__(
++              " rep; nop                      \n");
++}
++
++#endif         /* __i386__ */
++
++
++#ifdef __x86_64__             /* AMD Opteron, Intel EM64T */
++#define HAS_TEST_AND_SET
++
++typedef unsigned char slock_t;
++
++#define TAS(lock) tas(lock)
++
++static __inline__ int
++tas(volatile slock_t *lock)
++{
++      register slock_t _res = 1;
++
++      /*
++       * On Opteron, using a non-locking test before the locking instruction
++       * is a huge loss.  On EM64T, it appears to be a wash or small loss,
++       * so we needn't bother to try to distinguish the sub-architectures.
++       */
++      __asm__ __volatile__(
++              "       lock                    \n"
++              "       xchgb   %0,%1   \n"
++:             "+q"(_res), "+m"(*lock)
++:
++:             "memory", "cc");
++      return (int) _res;
++}
++
++#define SPIN_DELAY() spin_delay()
++
++static __inline__ void
++spin_delay(void)
++{
++      /*
++       * Adding a PAUSE in the spin delay loop is demonstrably a no-op on
++       * Opteron, but it may be of some use on EM64T, so we keep it.
++       */
++      __asm__ __volatile__(
++              " rep; nop                      \n");
++}
++
++#endif         /* __x86_64__ */
++
++
++#if defined(__ia64__) || defined(__ia64)      /* Intel Itanium */
++#define HAS_TEST_AND_SET
++
++typedef unsigned int slock_t;
++
++#define TAS(lock) tas(lock)
++
++#ifndef __INTEL_COMPILER
++
++static __inline__ int
++tas(volatile slock_t *lock)
++{
++      long int        ret;
++
++      __asm__ __volatile__(
++              "       xchg4   %0=%1,%2        \n"
++:             "=r"(ret), "+m"(*lock)
++:             "r"(1)
++:             "memory");
++      return (int) ret;
++}
 +
-+* Fix bug #8606 - ZEND_FETCH_GLOBAL is not an opcode, but is a 
-+  op1-&gt;type.  The opcodes applicable are ZEND_FETCH_R and 
-+  ZEND_FETCH_W. (Gopal)
++#else /* __INTEL_COMPILER */
 +
-+* PHP 5.2 Compatibility (Gopal)
++static __inline__ int
++tas(volatile slock_t *lock)
++{
++      int             ret;
 +
-+* Make the include_once override optional - default off (Sara)
++      ret = _InterlockedExchange(lock,1);     /* this is a xchg asm macro */
 +
-+* Fixed crash when apc run in CLI, but enable_cli is off. (Ilia)
++      return ret;
++}
 +
-+* Ensure that the apc_globals-&gt;cache_stack is cleared before the 
-+  shm cache is destroyed. Fixes segfault for corner-case i.e request
-+  shutdown (apc_deactivate) is not called before module shutdown 
-+  calls (php_apc_shutdown_globals)  (Gopal)
++#endif /* __INTEL_COMPILER */
++#endif         /* __ia64__ || __ia64 */
 +
-+* TSRM fixes (ensure ts_free_id before apc.so is dlclosed) (Gopal)
 +
-+* Fix memory leak of apc_cache_info_t-&gt;deleted_list (Gopal)</notes>
-+  </release>
-+  <release>
-+   <stability>
-+    <release>stable</release>
-+    <api>stable</api>
-+   </stability>
-+   <version>
-+    <release>3.0.12p1</release>
-+    <api>3.0.0</api>
-+   </version>
-+   <date>2006-09-05</date>
-+   <notes>* The only change here is a trivial PHP 4 build fix.</notes>
-+  </release>
-+  <release>
-+   <stability>
-+    <release>stable</release>
-+    <api>stable</api>
-+   </stability>
-+   <version>
-+    <release>3.0.12p2</release>
-+    <api>3.0.0</api>
-+   </version>
-+   <date>2006-09-05</date>
-+   <notes>* Let&apos;s get the version number right.  3.0.12p2 now.</notes>
-+  </release>
-+  <release>
-+   <stability>
-+    <release>stable</release>
-+    <api>stable</api>
-+   </stability>
-+   <version>
-+    <release>3.0.13</release>
-+    <api>3.0.0</api>
-+   </version>
-+   <date>2007-02-24</date>
-+   <notes>* PHP 5.2 file upload progress tracking support (Rasmus)
-+* Pthread mutex and spin locks (Shire)
-+* Recursive zval support for apc_fetch/_store (Shire, Gopal)
-+* apc.stat_ctime flag for ctime checks (Rasmus)
-+* Multiple key fetches with apc_fetch (Shire)
-+* Canary checks for shm memory deallocation (Gopal)
-+* Add hooks for external optimizer (Shire)
-+* Obsolete and remove apc optimizer (Gopal)
-+* APC info changes - cache insert rate, hit and miss rates (Shire)
-+* Fix apc_load_constants (Gopal)
-+* Rewrite dump opcode code to use vld (Gopal)
-+* Use apc_[ewn]print functions for error reporting (Shire) 
-+* Auto global fixes and refactoring (Gopal, Shire)
-+* Fix memory leaks in object serialization (Ilia)
-+* Memory cleanup code for destructor order (Gopal)
-+* Win32 build fixes (Ilia, Wez)
-+* ZTS and Php 4 build fixes (Bjori)
-+* Add apc_add() function (Rasmus)
-+* Add optional limited flag to apc_sma_info() (Rasmus)</notes>
-+  </release>
-+  <release>
-+   <stability>
-+    <release>stable</release>
-+    <api>stable</api>
-+   </stability>
-+   <version>
-+    <release>3.0.14</release>
-+    <api>3.0.0</api>
-+   </version>
-+   <date>2007-04-02</date>
-+   <notes>* Build fix (Shire)
-+* Don&apos;t hook the upload hook if APC is disabled (Rasmus)
-+* Local shadow cache support (Gopal)
-+* Avoid uneccessary loops over op_arrays for &quot;known&quot; auto-globals (Gopal)
-+* Fix apc_add() to overwrite timed out user entries (Rasmus)
-+* Fix double inclusion of files with conditional classes in php4 (Gopal)
-+* Allocator fixes to reduce fragmentation (Gopal)</notes>
-+  </release>
-+  <release>
-+   <stability>
-+    <release>stable</release>
-+    <api>stable</api>
-+   </stability>
-+   <version>
-+    <release>3.0.15</release>
-+    <api>3.0.0</api>
-+   </version>
-+   <date>2007-10-18</date>
-+   <notes>* Eliminate a per-request time() syscall (Rasmus)
-+* Added rfc1867 prefix, name, and freq ini options (Shire)
-+* Allow deletion of individual user cache entries via apc.php (Sara)
-+* Fix overzealous cleanup during RSHUTDOWN (Gopal)
-+* Fix memory alignment and locking issues (Gopal)
-+* Make apc_compile insert/replace entries (Shire)
-+* Make mixed inheritance recompile &amp; cache afresh  (Gopal)
-+* Make nostat mode search include_path for canonicalization (Gopal)
-+* ZTS &amp; other compile fixes (Gopal, Edin, Shire)</notes>
-+  </release>
-+ </changelog>
-+</package>
-diff -ubrN php-5.2.5-orig/ext/apc/pgsql_s_lock.c php-5.2.5/ext/apc/pgsql_s_lock.c
---- php-5.2.5-orig/ext/apc/pgsql_s_lock.c      1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/pgsql_s_lock.c   2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,481 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2007 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | The following code was ported from the PostgreSQL project, please    |
-+  |  see appropriate copyright notices that follow.                      |
-+  | Initial conversion by Brian Shire <shire@php.net>                    |
-+  +----------------------------------------------------------------------+
++#if defined(__arm__) || defined(__arm)
++#define HAS_TEST_AND_SET
 +
-+ */
++typedef unsigned char slock_t;
 +
-+/* $Id: pgsql_s_lock.c,v 3.2 2007/02/25 05:19:11 shire Exp $ */
++#define TAS(lock) tas(lock)
 +
-+/*-------------------------------------------------------------------------
-+ *
-+ * s_lock.c
-+ *       Hardware-dependent implementation of spinlocks.
-+ *
-+ *
-+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
-+ * Portions Copyright (c) 1994, Regents of the University of California
-+ *
-+ *
-+ * IDENTIFICATION
-+ *      $PostgreSQL: pgsql/src/backend/storage/lmgr/s_lock.c,v 1.47 2006/10/04 00:29:58 momjian Exp $
-+ *
-+ *-------------------------------------------------------------------------
-+ */
-+/* #include "postgres.h"  -- Removed for APC */
++static __inline__ int
++tas(volatile slock_t *lock)
++{
++      register slock_t _res = 1;
 +
-+/* -- Added for APC -- */
-+#include "apc.h"
-+#ifdef APC_SPIN_LOCKS
++      __asm__ __volatile__(
++              "       swpb    %0, %0, [%2]    \n"
++:             "+r"(_res), "+m"(*lock)
++:             "r"(lock)
++:             "memory");
++      return (int) _res;
++}
 +
-+#ifdef S_LOCK_TEST
-+#include <stdio.h>
-+#endif
-+#ifndef WIN32
-+#include <sys/select.h>
-+#endif
-+/* ---- */
++#endif         /* __arm__ */
 +
-+#include <time.h>
-+#include <unistd.h>
 +
-+/* #include "storage/s_lock.h" -- Removed for APC */
-+#include "pgsql_s_lock.h"
++/* S/390 and S/390x Linux (32- and 64-bit zSeries) */
++#if defined(__s390__) || defined(__s390x__)
++#define HAS_TEST_AND_SET
 +
-+static int    spins_per_delay = DEFAULT_SPINS_PER_DELAY;
++typedef unsigned int slock_t;
 +
++#define TAS(lock)        tas(lock)
 +
-+/* -- APC specific additions ------------------------------*/
-+/* The following dependencies have been copied from 
-+ * other pgsql source files.  The original locations 
-+ * have been noted.
-+ */
++static __inline__ int
++tas(volatile slock_t *lock)
++{
++      int                     _res = 0;
 +
-+/* -- from include/c.h -- */
-+#ifndef TRUE
-+#define TRUE  1
-+#endif
++      __asm__ __volatile__(
++              "       cs      %0,%3,0(%2)             \n"
++:             "+d"(_res), "+m"(*lock)
++:             "a"(lock), "d"(1)
++:             "memory", "cc");
++      return _res;
++}
 +
-+#ifndef FALSE
-+#define FALSE 0
-+#endif
++#endif         /* __s390__ || __s390x__ */
 +
-+/* -- from include/pg_config_manual.h -- */
-+#define MAX_RANDOM_VALUE (0x7FFFFFFF) 
 +
-+/*
-+ * Max
-+ *    Return the maximum of two numbers.
-+ */
-+#define Max(x, y)   ((x) > (y) ? (x) : (y))
++#if defined(__sparc__)                /* Sparc */
++#define HAS_TEST_AND_SET
 +
-+/* -- from include/c.h -- */
-+/*
-+ * Min
-+ *    Return the minimum of two numbers.
-+ */
-+#define Min(x, y)   ((x) < (y) ? (x) : (y))
++typedef unsigned char slock_t;
 +
++#define TAS(lock) tas(lock)
 +
-+/* -- from backend/port/win32/signal.c -- */
-+/*
-+ * pg_usleep --- delay the specified number of microseconds.
-+ *
-+ * NOTE: although the delay is specified in microseconds, the effective
-+ * resolution is only 1/HZ, or 10 milliseconds, on most Unixen.  Expect
-+ * the requested delay to be rounded up to the next resolution boundary.
-+ *
-+ * On machines where "long" is 32 bits, the maximum delay is ~2000 seconds.
-+ */
-+void
-+pg_usleep(long microsec)
++static __inline__ int
++tas(volatile slock_t *lock)
 +{
-+      if (microsec > 0)
-+      {
-+#ifndef WIN32
-+              struct timeval delay;
++      register slock_t _res;
 +
-+              delay.tv_sec = microsec / 1000000L;
-+              delay.tv_usec = microsec % 1000000L;
-+              (void) select(0, NULL, NULL, NULL, &delay);
-+#else
-+              SleepEx((microsec < 500 ? 1 : (microsec + 500) / 1000), FALSE);
-+#endif
-+      }
++      /*
++       *      See comment in /pg/backend/port/tas/solaris_sparc.s for why this
++       *      uses "ldstub", and that file uses "cas".  gcc currently generates
++       *      sparcv7-targeted binaries, so "cas" use isn't possible.
++       */
++      __asm__ __volatile__(
++              "       ldstub  [%2], %0        \n"
++:             "=r"(_res), "+m"(*lock)
++:             "r"(lock)
++:             "memory");
++      return (int) _res;
 +}
 +
-+/* -- End APC specific additions ------------------------------*/
++#endif         /* __sparc__ */
 +
 +
-+/*
-+ * s_lock_stuck() - complain about a stuck spinlock
-+ */
-+static void
-+s_lock_stuck(volatile slock_t *lock, const char *file, int line)
-+{
-+#if defined(S_LOCK_TEST)
-+      fprintf(stderr,
-+                      "\nStuck spinlock (%p) detected at %s:%d.\n",
-+                      lock, file, line);
-+      exit(1);
++/* PowerPC */
++#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
++#define HAS_TEST_AND_SET
++
++#if defined(__ppc64__) || defined(__powerpc64__)
++typedef unsigned long slock_t;
 +#else
-+  /* -- Removed for APC
-+      elog(PANIC, "stuck spinlock (%p) detected at %s:%d",
-+               lock, file, line);
-+  */
-+  apc_eprint("Stuck spinlock (%p) detected", lock);
++typedef unsigned int slock_t;
 +#endif
-+}
-+
 +
++#define TAS(lock) tas(lock)
 +/*
-+ * s_lock(lock) - platform-independent portion of waiting for a spinlock.
++ * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002,
++ * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop.
 + */
-+void
-+s_lock(volatile slock_t *lock, const char *file, int line)
++static __inline__ int
++tas(volatile slock_t *lock)
 +{
-+      /*
-+       * We loop tightly for awhile, then delay using pg_usleep() and try again.
-+       * Preferably, "awhile" should be a small multiple of the maximum time we
-+       * expect a spinlock to be held.  100 iterations seems about right as an
-+       * initial guess.  However, on a uniprocessor the loop is a waste of
-+       * cycles, while in a multi-CPU scenario it's usually better to spin a bit
-+       * longer than to call the kernel, so we try to adapt the spin loop count
-+       * depending on whether we seem to be in a uniprocessor or multiprocessor.
-+       *
-+       * Note: you might think MIN_SPINS_PER_DELAY should be just 1, but you'd
-+       * be wrong; there are platforms where that can result in a "stuck
-+       * spinlock" failure.  This has been seen particularly on Alphas; it seems
-+       * that the first TAS after returning from kernel space will always fail
-+       * on that hardware.
-+       *
-+       * Once we do decide to block, we use randomly increasing pg_usleep()
-+       * delays. The first delay is 1 msec, then the delay randomly increases to
-+       * about one second, after which we reset to 1 msec and start again.  The
-+       * idea here is that in the presence of heavy contention we need to
-+       * increase the delay, else the spinlock holder may never get to run and
-+       * release the lock.  (Consider situation where spinlock holder has been
-+       * nice'd down in priority by the scheduler --- it will not get scheduled
-+       * until all would-be acquirers are sleeping, so if we always use a 1-msec
-+       * sleep, there is a real possibility of starvation.)  But we can't just
-+       * clamp the delay to an upper bound, else it would take a long time to
-+       * make a reasonable number of tries.
-+       *
-+       * We time out and declare error after NUM_DELAYS delays (thus, exactly
-+       * that many tries).  With the given settings, this will usually take 2 or
-+       * so minutes.  It seems better to fix the total number of tries (and thus
-+       * the probability of unintended failure) than to fix the total time
-+       * spent.
-+       *
-+       * The pg_usleep() delays are measured in milliseconds because 1 msec is a
-+       * common resolution limit at the OS level for newer platforms. On older
-+       * platforms the resolution limit is usually 10 msec, in which case the
-+       * total delay before timeout will be a bit more.
-+       */
-+#define MIN_SPINS_PER_DELAY 10
-+#define MAX_SPINS_PER_DELAY 1000
-+#define NUM_DELAYS                    1000
-+#define MIN_DELAY_MSEC                1
-+#define MAX_DELAY_MSEC                1000
-+
-+      int                     spins = 0;
-+      int                     delays = 0;
-+      int                     cur_delay = 0;
-+  
-+      while (TAS(lock))
-+      {
-+              /* CPU-specific delay each time through the loop */
-+              SPIN_DELAY();
++      slock_t _t;
++      int _res;
 +
-+              /* Block the process every spins_per_delay tries */
-+              if (++spins >= spins_per_delay)
-+              {
-+                      if (++delays > NUM_DELAYS)
-+                              s_lock_stuck(lock, file, line);
++      __asm__ __volatile__(
++"     lwarx   %0,0,%3         \n"
++"     cmpwi   %0,0            \n"
++"     bne     1f                      \n"
++"     addi    %0,%0,1         \n"
++"     stwcx.  %0,0,%3         \n"
++"     beq     2f              \n"
++"1:   li      %1,1            \n"
++"     b               3f                      \n"
++"2:                                           \n"
++"     isync                           \n"
++"     li      %1,0            \n"
++"3:                                           \n"
 +
-+                      if (cur_delay == 0) /* first time to delay? */
-+                              cur_delay = MIN_DELAY_MSEC;
++:     "=&r"(_t), "=r"(_res), "+m"(*lock)
++:     "r"(lock)
++:     "memory", "cc");
++      return _res;
++}
 +
-+                      pg_usleep(cur_delay * 1000L);
++/* PowerPC S_UNLOCK is almost standard but requires a "sync" instruction */
++#define S_UNLOCK(lock)        \
++do \
++{ \
++      __asm__ __volatile__ (" sync \n"); \
++      *((volatile slock_t *) (lock)) = 0; \
++} while (0)
 +
-+#if defined(S_LOCK_TEST)
-+                      fprintf(stdout, "*");
-+                      fflush(stdout);
-+#endif
++#endif /* powerpc */
 +
-+                      /* increase delay by a random fraction between 1X and 2X */
-+                      cur_delay += (int) (cur_delay *
-+                                        ((double) random() / (double) MAX_RANDOM_VALUE) + 0.5);
-+                      /* wrap back to minimum delay when max is exceeded */
-+                      if (cur_delay > MAX_DELAY_MSEC)
-+                              cur_delay = MIN_DELAY_MSEC;
 +
-+                      spins = 0;
-+              }
-+      }
++/* Linux Motorola 68k */
++#if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__)
++#define HAS_TEST_AND_SET
 +
-+      /*
-+       * If we were able to acquire the lock without delaying, it's a good
-+       * indication we are in a multiprocessor.  If we had to delay, it's a sign
-+       * (but not a sure thing) that we are in a uniprocessor. Hence, we
-+       * decrement spins_per_delay slowly when we had to delay, and increase it
-+       * rapidly when we didn't.  It's expected that spins_per_delay will
-+       * converge to the minimum value on a uniprocessor and to the maximum
-+       * value on a multiprocessor.
-+       *
-+       * Note: spins_per_delay is local within our current process. We want to
-+       * average these observations across multiple backends, since it's
-+       * relatively rare for this function to even get entered, and so a single
-+       * backend might not live long enough to converge on a good value.      That
-+       * is handled by the two routines below.
-+       */
-+      if (cur_delay == 0)
-+      {
-+              /* we never had to delay */
-+              if (spins_per_delay < MAX_SPINS_PER_DELAY)
-+                      spins_per_delay = Min(spins_per_delay + 100, MAX_SPINS_PER_DELAY);
-+      }
-+      else
-+      {
-+              if (spins_per_delay > MIN_SPINS_PER_DELAY)
-+                      spins_per_delay = Max(spins_per_delay - 1, MIN_SPINS_PER_DELAY);
-+      }
-+}
++typedef unsigned char slock_t;
 +
++#define TAS(lock) tas(lock)
 +
-+#if 0  /* -- APC doesn't use the set_spins_per_delay or update_spins_per_delay -- */
-+/*
-+ * Set local copy of spins_per_delay during backend startup.
-+ *
-+ * NB: this has to be pretty fast as it is called while holding a spinlock
-+ */
-+void
-+set_spins_per_delay(int shared_spins_per_delay)
++static __inline__ int
++tas(volatile slock_t *lock)
 +{
-+      spins_per_delay = shared_spins_per_delay;
++      register int rv;
++
++      __asm__ __volatile__(
++              "       clrl    %0              \n"
++              "       tas             %1              \n"
++              "       sne             %0              \n"
++:             "=d"(rv), "+m"(*lock)
++:
++:             "memory", "cc");
++      return rv;
 +}
 +
++#endif         /* (__mc68000__ || __m68k__) && __linux__ */
++
++
 +/*
-+ * Update shared estimate of spins_per_delay during backend exit.
-+ *
-+ * NB: this has to be pretty fast as it is called while holding a spinlock
++ * VAXen -- even multiprocessor ones
++ * (thanks to Tom Ivar Helbekkmo)
 + */
-+int
-+update_spins_per_delay(int shared_spins_per_delay)
++#if defined(__vax__)
++#define HAS_TEST_AND_SET
++
++typedef unsigned char slock_t;
++
++#define TAS(lock) tas(lock)
++
++static __inline__ int
++tas(volatile slock_t *lock)
 +{
-+      /*
-+       * We use an exponential moving average with a relatively slow adaption
-+       * rate, so that noise in any one backend's result won't affect the shared
-+       * value too much.      As long as both inputs are within the allowed range,
-+       * the result must be too, so we need not worry about clamping the result.
-+       *
-+       * We deliberately truncate rather than rounding; this is so that single
-+       * adjustments inside a backend can affect the shared estimate (see the
-+       * asymmetric adjustment rules above).
-+       */
-+      return (shared_spins_per_delay * 15 + spins_per_delay) / 16;
++      register int    _res;
++
++      __asm__ __volatile__(
++              "       movl    $1, %0                  \n"
++              "       bbssi   $0, (%2), 1f    \n"
++              "       clrl    %0                              \n"
++              "1: \n"
++:             "=&r"(_res), "+m"(*lock)
++:             "r"(lock)
++:             "memory");
++      return _res;
 +}
-+#endif
 +
-+/*
-+ * Various TAS implementations that cannot live in s_lock.h as no inline
-+ * definition exists (yet).
-+ * In the future, get rid of tas.[cso] and fold it into this file.
-+ *
-+ * If you change something here, you will likely need to modify s_lock.h too,
-+ * because the definitions for these are split between this file and s_lock.h.
-+ */
++#endif         /* __vax__ */
 +
 +
-+#ifdef HAVE_SPINLOCKS                 /* skip spinlocks if requested */
++#if defined(__ns32k__)                /* National Semiconductor 32K */
++#define HAS_TEST_AND_SET
++
++typedef unsigned char slock_t;
++
++#define TAS(lock) tas(lock)
++
++static __inline__ int
++tas(volatile slock_t *lock)
++{
++      register int    _res;
++
++      __asm__ __volatile__(
++              "       sbitb   0, %1   \n"
++              "       sfsd    %0              \n"
++:             "=r"(_res), "+m"(*lock)
++:
++:             "memory");
++      return _res;
++}
 +
++#endif         /* __ns32k__ */
 +
-+#if defined(__GNUC__)
 +
++#if defined(__alpha) || defined(__alpha__)    /* Alpha */
 +/*
-+ * All the gcc flavors that are not inlined
++ * Correct multi-processor locking methods are explained in section 5.5.3
++ * of the Alpha AXP Architecture Handbook, which at this writing can be
++ * found at ftp://ftp.netbsd.org/pub/NetBSD/misc/dec-docs/index.html.
++ * For gcc we implement the handbook's code directly with inline assembler.
 + */
++#define HAS_TEST_AND_SET
 +
++typedef unsigned long slock_t;
 +
-+/*
-+ * Note: all the if-tests here probably ought to be testing gcc version
-+ * rather than platform, but I don't have adequate info to know what to
-+ * write.  Ideally we'd flush all this in favor of the inline version.
-+ */
-+#if defined(__m68k__) && !defined(__linux__)
-+/* really means: extern int tas(slock_t* **lock); */
-+static void
-+tas_dummy()
++#define TAS(lock)  tas(lock)
++
++static __inline__ int
++tas(volatile slock_t *lock)
 +{
-+      __asm__         __volatile__(
-+#if defined(__NetBSD__) && defined(__ELF__)
-+/* no underscore for label and % for registers */
-+                                                                               "\
-+.global               tas                             \n\
-+tas:                                                  \n\
-+                      movel   %sp@(0x4),%a0   \n\
-+                      tas     %a0@            \n\
-+                      beq     _success        \n\
-+                      moveq   #-128,%d0       \n\
-+                      rts                             \n\
-+_success:                                             \n\
-+                      moveq   #0,%d0          \n\
-+                      rts                             \n"
-+#else
-+                                                                               "\
-+.global               _tas                            \n\
-+_tas:                                                 \n\
-+                      movel   sp@(0x4),a0     \n\
-+                      tas     a0@                     \n\
-+                      beq     _success        \n\
-+                      moveq   #-128,d0        \n\
-+                      rts                                     \n\
-+_success:                                             \n\
-+                      moveq   #0,d0           \n\
-+                      rts                                     \n"
-+#endif   /* __NetBSD__ && __ELF__ */
-+      );
-+}
-+#endif   /* __m68k__ && !__linux__ */
-+#else                                                 /* not __GNUC__ */
++      register slock_t _res;
 +
-+/*
-+ * All non gcc
-+ */
++      __asm__ __volatile__(
++              "       ldq             $0, %1  \n"
++              "       bne             $0, 2f  \n"
++              "       ldq_l   %0, %1  \n"
++              "       bne             %0, 2f  \n"
++              "       mov             1,  $0  \n"
++              "       stq_c   $0, %1  \n"
++              "       beq             $0, 2f  \n"
++              "       mb                              \n"
++              "       br              3f              \n"
++              "2:     mov             1, %0   \n"
++              "3:                                     \n"
++:             "=&r"(_res), "+m"(*lock)
++:
++:             "memory", "0");
++      return (int) _res;
++}
 +
++#define S_UNLOCK(lock)        \
++do \
++{\
++      __asm__ __volatile__ (" mb \n"); \
++      *((volatile slock_t *) (lock)) = 0; \
++} while (0)
 +
-+#if defined(sun3)
-+static void
-+tas_dummy()                                           /* really means: extern int tas(slock_t
-+                                                               * *lock); */
-+{
-+      asm("LLA0:");
-+      asm("   .data");
-+      asm("   .text");
-+      asm("|#PROC# 04");
-+      asm("   .globl  _tas");
-+      asm("_tas:");
-+      asm("|#PROLOGUE# 1");
-+      asm("   movel   sp@(0x4),a0");
-+      asm("   tas a0@");
-+      asm("   beq LLA1");
-+      asm("   moveq   #-128,d0");
-+      asm("   rts");
-+      asm("LLA1:");
-+      asm("   moveq   #0,d0");
-+      asm("   rts");
-+      asm("   .data");
-+}
-+#endif   /* sun3 */
-+#endif   /* not __GNUC__ */
-+#endif   /* HAVE_SPINLOCKS */
++#endif /* __alpha || __alpha__ */
 +
 +
++#if defined(__mips__) && !defined(__sgi)      /* non-SGI MIPS */
++/* Note: on SGI we use the OS' mutex ABI, see below */
++/* Note: R10000 processors require a separate SYNC */
++#define HAS_TEST_AND_SET
 +
-+/*****************************************************************************/
-+#if defined(S_LOCK_TEST)
++typedef unsigned int slock_t;
 +
-+/*
-+ * test program for verifying a port's spinlock support.
-+ */
++#define TAS(lock) tas(lock)
 +
-+struct test_lock_struct
++static __inline__ int
++tas(volatile slock_t *lock)
 +{
-+      char            pad1;
-+      slock_t         lock;
-+      char            pad2;
-+};
++      register volatile slock_t *_l = lock;
++      register int _res;
++      register int _tmp;
 +
-+volatile struct test_lock_struct test_lock;
++      __asm__ __volatile__(
++              "       .set push           \n"
++              "       .set mips2          \n"
++              "       .set noreorder      \n"
++              "       .set nomacro        \n"
++              "       ll      %0, %2      \n"
++              "       or      %1, %0, 1   \n"
++              "       sc      %1, %2      \n"
++              "       xori    %1, 1       \n"
++              "       or      %0, %0, %1  \n"
++              "       sync                \n"
++              "       .set pop              "
++:             "=&r" (_res), "=&r" (_tmp), "+R" (*_l)
++:
++:             "memory");
++      return _res;
++}
 +
-+int
-+main()
-+{
-+      srandom((unsigned int) time(NULL));
++/* MIPS S_UNLOCK is almost standard but requires a "sync" instruction */
++#define S_UNLOCK(lock)        \
++do \
++{ \
++      __asm__ __volatile__( \
++              "       .set push           \n" \
++              "       .set mips2          \n" \
++              "       .set noreorder      \n" \
++              "       .set nomacro        \n" \
++              "       sync                \n" \
++              "       .set pop              "); \
++      *((volatile slock_t *) (lock)) = 0; \
++} while (0)
 +
-+      test_lock.pad1 = test_lock.pad2 = 0x44;
++#endif /* __mips__ && !__sgi */
 +
-+      S_INIT_LOCK(&test_lock.lock);
 +
-+      if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
-+      {
-+              printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
-+              return 1;
-+      }
++/* These live in s_lock.c, but only for gcc */
 +
-+      if (!S_LOCK_FREE(&test_lock.lock))
-+      {
-+              printf("S_LOCK_TEST: failed, lock not initialized\n");
-+              return 1;
-+      }
 +
-+      S_LOCK(&test_lock.lock);
++#if defined(__m68k__) && !defined(__linux__)  /* non-Linux Motorola 68k */
++#define HAS_TEST_AND_SET
 +
-+      if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
-+      {
-+              printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
-+              return 1;
-+      }
++typedef unsigned char slock_t;
++#endif
 +
-+      if (S_LOCK_FREE(&test_lock.lock))
-+      {
-+              printf("S_LOCK_TEST: failed, lock not locked\n");
-+              return 1;
-+      }
 +
-+      S_UNLOCK(&test_lock.lock);
++#endif        /* __GNUC__ */
 +
-+      if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
-+      {
-+              printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
-+              return 1;
-+      }
 +
-+      if (!S_LOCK_FREE(&test_lock.lock))
-+      {
-+              printf("S_LOCK_TEST: failed, lock not unlocked\n");
-+              return 1;
-+      }
 +
-+      S_LOCK(&test_lock.lock);
++/*
++ * ---------------------------------------------------------------------
++ * Platforms that use non-gcc inline assembly:
++ * ---------------------------------------------------------------------
++ */
 +
-+      if (test_lock.pad1 != 0x44 || test_lock.pad2 != 0x44)
-+      {
-+              printf("S_LOCK_TEST: failed, declared datatype is wrong size\n");
-+              return 1;
-+      }
++#if !defined(HAS_TEST_AND_SET)        /* We didn't trigger above, let's try here */
 +
-+      if (S_LOCK_FREE(&test_lock.lock))
-+      {
-+              printf("S_LOCK_TEST: failed, lock not re-locked\n");
-+              return 1;
-+      }
 +
-+      printf("S_LOCK_TEST: this will print %d stars and then\n", NUM_DELAYS);
-+      printf("             exit with a 'stuck spinlock' message\n");
-+      printf("             if S_LOCK() and TAS() are working.\n");
-+      fflush(stdout);
++#if defined(USE_UNIVEL_CC)            /* Unixware compiler */
++#define HAS_TEST_AND_SET
 +
-+      s_lock(&test_lock.lock, __FILE__, __LINE__);
++typedef unsigned char slock_t;
 +
-+      printf("S_LOCK_TEST: failed, lock not locked\n");
-+      return 1;
++#define TAS(lock)     tas(lock)
++
++asm int
++tas(volatile slock_t *s_lock)
++{
++/* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
++%mem s_lock
++      pushl %ebx
++      movl s_lock, %ebx
++      movl $255, %eax
++      lock
++      xchgb %al, (%ebx)
++      popl %ebx
 +}
 +
-+#endif   /* S_LOCK_TEST */
++#endif         /* defined(USE_UNIVEL_CC) */
++
++
++#if defined(__alpha) || defined(__alpha__)    /* Tru64 Unix Alpha compiler */
++/*
++ * The Tru64 compiler doesn't support gcc-style inline asm, but it does
++ * have some builtin functions that accomplish much the same results.
++ * For simplicity, slock_t is defined as long (ie, quadword) on Alpha
++ * regardless of the compiler in use.  LOCK_LONG and UNLOCK_LONG only
++ * operate on an int (ie, longword), but that's OK as long as we define
++ * S_INIT_LOCK to zero out the whole quadword.
++ */
++#define HAS_TEST_AND_SET
++
++typedef unsigned long slock_t;
 +
-+#endif /* APC_SPIN_LOCKS */
-diff -ubrN php-5.2.5-orig/ext/apc/pgsql_s_lock.h php-5.2.5/ext/apc/pgsql_s_lock.h
---- php-5.2.5-orig/ext/apc/pgsql_s_lock.h      1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/pgsql_s_lock.h   2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,928 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2007 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | The following code was ported from the PostgreSQL project, please    |
-+  |  see appropriate copyright notices that follow.                      |
-+  | Initial conversion by Brian Shire <shire@php.net>                    |
-+  +----------------------------------------------------------------------+
++#include <alpha/builtins.h>
++#define S_INIT_LOCK(lock)  (*(lock) = 0)
++#define TAS(lock)                (__LOCK_LONG_RETRY((lock), 1) == 0)
++#define S_UNLOCK(lock)           __UNLOCK_LONG(lock)
 +
-+ */
++#endif         /* __alpha || __alpha__ */
 +
-+/* $Id: pgsql_s_lock.h,v 3.3 2007/02/16 21:28:04 shire Exp $ */
 +
-+/*-------------------------------------------------------------------------
-+ *
-+ * s_lock.h
-+ *       Hardware-dependent implementation of spinlocks.
-+ *
-+ *    NOTE: none of the macros in this file are intended to be called directly.
-+ *    Call them through the hardware-independent macros in spin.h.
-+ *
-+ *    The following hardware-dependent macros must be provided for each
-+ *    supported platform:
-+ *
-+ *    void S_INIT_LOCK(slock_t *lock)
-+ *            Initialize a spinlock (to the unlocked state).
-+ *
-+ *    void S_LOCK(slock_t *lock)
-+ *            Acquire a spinlock, waiting if necessary.
-+ *            Time out and abort() if unable to acquire the lock in a
-+ *            "reasonable" amount of time --- typically ~ 1 minute.
-+ *
-+ *    void S_UNLOCK(slock_t *lock)
-+ *            Unlock a previously acquired lock.
-+ *
-+ *    bool S_LOCK_FREE(slock_t *lock)
-+ *            Tests if the lock is free. Returns TRUE if free, FALSE if locked.
-+ *            This does *not* change the state of the lock.
-+ *
-+ *    void SPIN_DELAY(void)
-+ *            Delay operation to occur inside spinlock wait loop.
-+ *
-+ *    Note to implementors: there are default implementations for all these
-+ *    macros at the bottom of the file.  Check if your platform can use
-+ *    these or needs to override them.
-+ *
-+ *  Usually, S_LOCK() is implemented in terms of an even lower-level macro
-+ *    TAS():
-+ *
-+ *    int TAS(slock_t *lock)
-+ *            Atomic test-and-set instruction.  Attempt to acquire the lock,
-+ *            but do *not* wait.      Returns 0 if successful, nonzero if unable
-+ *            to acquire the lock.
-+ *
-+ *    TAS() is NOT part of the API, and should never be called directly.
-+ *
-+ *    CAUTION: on some platforms TAS() may sometimes report failure to acquire
-+ *    a lock even when the lock is not locked.  For example, on Alpha TAS()
-+ *    will "fail" if interrupted.  Therefore TAS() should always be invoked
-+ *    in a retry loop, even if you are certain the lock is free.
-+ *
-+ *    ANOTHER CAUTION: be sure that TAS() and S_UNLOCK() represent sequence
-+ *    points, ie, loads and stores of other values must not be moved across
-+ *    a lock or unlock.  In most cases it suffices to make the operation be
-+ *    done through a "volatile" pointer.
-+ *
-+ *    On most supported platforms, TAS() uses a tas() function written
-+ *    in assembly language to execute a hardware atomic-test-and-set
-+ *    instruction.  Equivalent OS-supplied mutex routines could be used too.
-+ *
-+ *    If no system-specific TAS() is available (ie, HAVE_SPINLOCKS is not
-+ *    defined), then we fall back on an emulation that uses SysV semaphores
-+ *    (see spin.c).  This emulation will be MUCH MUCH slower than a proper TAS()
-+ *    implementation, because of the cost of a kernel call per lock or unlock.
-+ *    An old report is that Postgres spends around 40% of its time in semop(2)
-+ *    when using the SysV semaphore code.
-+ *
-+ *
-+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
-+ * Portions Copyright (c) 1994, Regents of the University of California
++#if defined(__hppa) || defined(__hppa__)      /* HP PA-RISC, GCC and HP compilers */
++/*
++ * HP's PA-RISC
 + *
-+ *      $PostgreSQL: pgsql/src/include/storage/s_lock.h,v 1.157 2006/06/07 22:24:45 momjian Exp $
++ * See src/backend/port/hpux/tas.c.template for details about LDCWX.  Because
++ * LDCWX requires a 16-byte-aligned address, we declare slock_t as a 16-byte
++ * struct.  The active word in the struct is whichever has the aligned address;
++ * the other three words just sit at -1.
 + *
-+ *-------------------------------------------------------------------------
++ * When using gcc, we can inline the required assembly code.
 + */
-+#ifndef S_LOCK_H
-+#define S_LOCK_H
++#define HAS_TEST_AND_SET
 +
-+/** APC namespace protection ************************************************/
-+/* hack to protect against any possible runtime namespace collisions...*/
-+#define pg_usleep               apc_spin_pg_usleep
-+#define s_lock                  apc_spin_s_lock
-+#define spins_per_delay         apc_spin_spins_per_delay
-+/****************************************************************************/
++typedef struct
++{
++      int                     sema[4];
++} slock_t;
 +
++#define TAS_ACTIVE_WORD(lock) ((volatile int *) (((long) (lock) + 15) & ~15))
 +
-+/* #include "storage/pg_sema.h"   -- Removed for APC */
++#if defined(__GNUC__)
 +
-+#define HAVE_SPINLOCKS 1 /* -- Added for APC */
++static __inline__ int
++tas(volatile slock_t *lock)
++{
++      volatile int *lockword = TAS_ACTIVE_WORD(lock);
++      register int lockval;
 +
-+#ifdef HAVE_SPINLOCKS /* skip spinlocks if requested */
++      __asm__ __volatile__(
++              "       ldcwx   0(0,%2),%0      \n"
++:             "=r"(lockval), "+m"(*lockword)
++:             "r"(lockword)
++:             "memory");
++      return (lockval == 0);
++}
 +
++#endif /* __GNUC__ */
 +
-+#if defined(__GNUC__) || defined(__ICC)
-+/*************************************************************************
-+ * All the gcc inlines
-+ * Gcc consistently defines the CPU as __cpu__.
-+ * Other compilers use __cpu or __cpu__ so we test for both in those cases.
-+ */
++#define S_UNLOCK(lock)        (*TAS_ACTIVE_WORD(lock) = -1)
 +
-+/*----------
-+ * Standard gcc asm format (assuming "volatile slock_t *lock"):
++#define S_INIT_LOCK(lock) \
++      do { \
++              volatile slock_t *lock_ = (lock); \
++              lock_->sema[0] = -1; \
++              lock_->sema[1] = -1; \
++              lock_->sema[2] = -1; \
++              lock_->sema[3] = -1; \
++      } while (0)
 +
-+      __asm__ __volatile__(
-+              "       instruction     \n"
-+              "       instruction     \n"
-+              "       instruction     \n"
-+:             "=r"(_res), "+m"(*lock)         // return register, in/out lock value
-+:             "r"(lock)                                       // lock pointer, in input register
-+:             "memory", "cc");                        // show clobbered registers here
++#define S_LOCK_FREE(lock)     (*TAS_ACTIVE_WORD(lock) != 0)
 +
-+ * The output-operands list (after first colon) should always include
-+ * "+m"(*lock), whether or not the asm code actually refers to this
-+ * operand directly.  This ensures that gcc believes the value in the
-+ * lock variable is used and set by the asm code.  Also, the clobbers
-+ * list (after third colon) should always include "memory"; this prevents
-+ * gcc from thinking it can cache the values of shared-memory fields
-+ * across the asm code.  Add "cc" if your asm code changes the condition
-+ * code register, and also list any temp registers the code uses.
-+ *----------
-+ */
++#endif         /* __hppa || __hppa__ */
 +
 +
-+#ifdef __i386__               /* 32-bit i386 */
++#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
++
 +#define HAS_TEST_AND_SET
 +
-+typedef unsigned char slock_t;
++typedef unsigned int slock_t;
 +
-+#define TAS(lock) tas(lock)
++#include <ia64/sys/inline.h>
++#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
 +
-+static __inline__ int
-+tas(volatile slock_t *lock)
-+{
-+      register slock_t _res = 1;
++#endif        /* HPUX on IA64, non gcc */
 +
-+      /*
-+       * Use a non-locking test before asserting the bus lock.  Note that the
-+       * extra test appears to be a small loss on some x86 platforms and a small
-+       * win on others; it's by no means clear that we should keep it.
-+       */
-+      __asm__ __volatile__(
-+              "       cmpb    $0,%1   \n"
-+              "       jne             1f              \n"
-+              "       lock                    \n"
-+              "       xchgb   %0,%1   \n"
-+              "1: \n"
-+:             "+q"(_res), "+m"(*lock)
-+:
-+:             "memory", "cc");
-+      return (int) _res;
-+}
 +
-+#define SPIN_DELAY() spin_delay()
++#if defined(__sgi)    /* SGI compiler */
++/*
++ * SGI IRIX 5
++ * slock_t is defined as a unsigned long. We use the standard SGI
++ * mutex API.
++ *
++ * The following comment is left for historical reasons, but is probably
++ * not a good idea since the mutex ABI is supported.
++ *
++ * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
++ * assembly from his NECEWS SVR4 port, but we probably ought to retain this
++ * for the R3000 chips out there.
++ */
++#define HAS_TEST_AND_SET
 +
-+static __inline__ void
-+spin_delay(void)
-+{
-+      /*
-+       * This sequence is equivalent to the PAUSE instruction ("rep" is
-+       * ignored by old IA32 processors if the following instruction is
-+       * not a string operation); the IA-32 Architecture Software
-+       * Developer's Manual, Vol. 3, Section 7.7.2 describes why using
-+       * PAUSE in the inner loop of a spin lock is necessary for good
-+       * performance:
-+       *
-+       *     The PAUSE instruction improves the performance of IA-32
-+       *     processors supporting Hyper-Threading Technology when
-+       *     executing spin-wait loops and other routines where one
-+       *     thread is accessing a shared lock or semaphore in a tight
-+       *     polling loop. When executing a spin-wait loop, the
-+       *     processor can suffer a severe performance penalty when
-+       *     exiting the loop because it detects a possible memory order
-+       *     violation and flushes the core processor's pipeline. The
-+       *     PAUSE instruction provides a hint to the processor that the
-+       *     code sequence is a spin-wait loop. The processor uses this
-+       *     hint to avoid the memory order violation and prevent the
-+       *     pipeline flush. In addition, the PAUSE instruction
-+       *     de-pipelines the spin-wait loop to prevent it from
-+       *     consuming execution resources excessively.
-+       */
-+      __asm__ __volatile__(
-+              " rep; nop                      \n");
-+}
++typedef unsigned long slock_t;
 +
-+#endif         /* __i386__ */
++#include "mutex.h"
++#define TAS(lock)     (test_and_set(lock,1))
++#define S_UNLOCK(lock)        (test_then_and(lock,0))
++#define S_INIT_LOCK(lock)     (test_then_and(lock,0))
++#define S_LOCK_FREE(lock)     (test_then_add(lock,0) == 0)
++#endif         /* __sgi */
 +
 +
-+#ifdef __x86_64__             /* AMD Opteron, Intel EM64T */
++#if defined(sinix)            /* Sinix */
++/*
++ * SINIX / Reliant UNIX
++ * slock_t is defined as a struct abilock_t, which has a single unsigned long
++ * member. (Basically same as SGI)
++ */
 +#define HAS_TEST_AND_SET
 +
-+typedef unsigned char slock_t;
-+
-+#define TAS(lock) tas(lock)
++#include "abi_mutex.h"
++typedef abilock_t slock_t;
 +
-+static __inline__ int
-+tas(volatile slock_t *lock)
-+{
-+      register slock_t _res = 1;
++#define TAS(lock)     (!acquire_lock(lock))
++#define S_UNLOCK(lock)        release_lock(lock)
++#define S_INIT_LOCK(lock)     init_lock(lock)
++#define S_LOCK_FREE(lock)     (stat_lock(lock) == UNLOCKED)
++#endif         /* sinix */
 +
-+      /*
-+       * On Opteron, using a non-locking test before the locking instruction
-+       * is a huge loss.  On EM64T, it appears to be a wash or small loss,
-+       * so we needn't bother to try to distinguish the sub-architectures.
-+       */
-+      __asm__ __volatile__(
-+              "       lock                    \n"
-+              "       xchgb   %0,%1   \n"
-+:             "+q"(_res), "+m"(*lock)
-+:
-+:             "memory", "cc");
-+      return (int) _res;
-+}
 +
-+#define SPIN_DELAY() spin_delay()
++#if defined(_AIX)     /* AIX */
++/*
++ * AIX (POWER)
++ */
++#define HAS_TEST_AND_SET
 +
-+static __inline__ void
-+spin_delay(void)
-+{
-+      /*
-+       * Adding a PAUSE in the spin delay loop is demonstrably a no-op on
-+       * Opteron, but it may be of some use on EM64T, so we keep it.
-+       */
-+      __asm__ __volatile__(
-+              " rep; nop                      \n");
-+}
++typedef unsigned int slock_t;
 +
-+#endif         /* __x86_64__ */
++#define TAS(lock)                     _check_lock(lock, 0, 1)
++#define S_UNLOCK(lock)                _clear_lock(lock, 0)
++#endif         /* _AIX */
 +
 +
-+#if defined(__ia64__) || defined(__ia64)      /* Intel Itanium */
++#if defined (nextstep)                /* Nextstep */
 +#define HAS_TEST_AND_SET
 +
-+typedef unsigned int slock_t;
-+
-+#define TAS(lock) tas(lock)
-+
-+#ifndef __INTEL_COMPILER
++typedef struct mutex slock_t;
 +
-+static __inline__ int
-+tas(volatile slock_t *lock)
-+{
-+      long int        ret;
++#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 0  /* -- APC: non-blocking lock not available in this case -- */
 +
-+      __asm__ __volatile__(
-+              "       xchg4   %0=%1,%2        \n"
-+:             "=r"(ret), "+m"(*lock)
-+:             "r"(1)
-+:             "memory");
-+      return (int) ret;
-+}
++#define S_LOCK(lock)  mutex_lock(lock)
++#define S_UNLOCK(lock)        mutex_unlock(lock)
++#define S_INIT_LOCK(lock)     mutex_init(lock)
++/* For Mach, we have to delve inside the entrails of `struct mutex'.  Ick! */
++#define S_LOCK_FREE(alock)    ((alock)->lock == 0)
++#endif         /* nextstep */
 +
-+#else /* __INTEL_COMPILER */
 +
-+static __inline__ int
-+tas(volatile slock_t *lock)
-+{
-+      int             ret;
++/* These are in s_lock.c */
 +
-+      ret = _InterlockedExchange(lock,1);     /* this is a xchg asm macro */
 +
-+      return ret;
-+}
++#if defined(sun3)             /* Sun3 */
++#define HAS_TEST_AND_SET
 +
-+#endif /* __INTEL_COMPILER */
-+#endif         /* __ia64__ || __ia64 */
++typedef unsigned char slock_t;
++#endif
 +
 +
-+#if defined(__arm__) || defined(__arm)
++#if defined(__sun) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
 +#define HAS_TEST_AND_SET
 +
++#if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus)
++typedef unsigned int slock_t;
++#else
 +typedef unsigned char slock_t;
++#endif
 +
-+#define TAS(lock) tas(lock)
-+
-+static __inline__ int
-+tas(volatile slock_t *lock)
-+{
-+      register slock_t _res = 1;
++extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with,
++                                                                        slock_t cmp);
 +
-+      __asm__ __volatile__(
-+              "       swpb    %0, %0, [%2]    \n"
-+:             "+r"(_res), "+m"(*lock)
-+:             "r"(lock)
-+:             "memory");
-+      return (int) _res;
-+}
++#define TAS(a) (pg_atomic_cas((a), 1, 0) != 0)
++#endif
 +
-+#endif         /* __arm__ */
 +
++#ifdef WIN32_ONLY_COMPILER
++typedef LONG slock_t;
 +
-+/* S/390 and S/390x Linux (32- and 64-bit zSeries) */
-+#if defined(__s390__) || defined(__s390x__)
 +#define HAS_TEST_AND_SET
++#define TAS(lock) (InterlockedCompareExchange(lock, 1, 0))
 +
-+typedef unsigned int slock_t;
-+
-+#define TAS(lock)        tas(lock)
++#define SPIN_DELAY() spin_delay()
 +
-+static __inline__ int
-+tas(volatile slock_t *lock)
++static __forceinline void
++spin_delay(void)
 +{
-+      int                     _res = 0;
-+
-+      __asm__ __volatile__(
-+              "       cs      %0,%3,0(%2)             \n"
-+:             "+d"(_res), "+m"(*lock)
-+:             "a"(lock), "d"(1)
-+:             "memory", "cc");
-+      return _res;
++      /* See comment for gcc code. Same code, MASM syntax */
++      __asm rep nop;
 +}
 +
-+#endif         /* __s390__ || __s390x__ */
++#endif
 +
++  
++#endif        /* !defined(HAS_TEST_AND_SET) */
 +
-+#if defined(__sparc__)                /* Sparc */
-+#define HAS_TEST_AND_SET
 +
-+typedef unsigned char slock_t;
++/* Blow up if we didn't have any way to do spinlocks */
++#ifndef HAS_TEST_AND_SET
++/* -- APC: We have better options in APC than this, that should be specified explicitly so just fail out and notify the user -- */
++#error Spin locking is not available on your platform, please select another locking method (see ./configure --help).
++/* #error PostgreSQL does not have native spinlock support on this platform.  To continue the compilation, rerun configure using --disable-spinlocks.  However, performance will be poor.  Please report this to pgsql-bugs@postgresql.org. */ 
++#endif
 +
-+#define TAS(lock) tas(lock)
 +
-+static __inline__ int
-+tas(volatile slock_t *lock)
-+{
-+      register slock_t _res;
++#else /* !HAVE_SPINLOCKS */
 +
-+      /*
-+       *      See comment in /pg/backend/port/tas/solaris_sparc.s for why this
-+       *      uses "ldstub", and that file uses "cas".  gcc currently generates
-+       *      sparcv7-targeted binaries, so "cas" use isn't possible.
-+       */
-+      __asm__ __volatile__(
-+              "       ldstub  [%2], %0        \n"
-+:             "=r"(_res), "+m"(*lock)
-+:             "r"(lock)
-+:             "memory");
-+      return (int) _res;
-+}
 +
-+#endif         /* __sparc__ */
++/*
++ * Fake spinlock implementation using semaphores --- slow and prone
++ * to fall foul of kernel limits on number of semaphores, so don't use this
++ * unless you must!  The subroutines appear in spin.c.
++ */
 +
++/* -- Removed for APC
++typedef PGSemaphoreData slock_t;
 +
-+/* PowerPC */
-+#if defined(__ppc__) || defined(__powerpc__) || defined(__ppc64__) || defined(__powerpc64__)
-+#define HAS_TEST_AND_SET
++extern bool s_lock_free_sema(volatile slock_t *lock);
++extern void s_unlock_sema(volatile slock_t *lock);
++extern void s_init_lock_sema(volatile slock_t *lock);
++extern int    tas_sema(volatile slock_t *lock);
++
++#define S_LOCK_FREE(lock)     s_lock_free_sema(lock)
++#define S_UNLOCK(lock)         s_unlock_sema(lock)
++#define S_INIT_LOCK(lock)     s_init_lock_sema(lock)
++#define TAS(lock)     tas_sema(lock)
++*/
++
++#endif        /* HAVE_SPINLOCKS */
 +
-+#if defined(__ppc64__) || defined(__powerpc64__)
-+typedef unsigned long slock_t;
-+#else
-+typedef unsigned int slock_t;
-+#endif
 +
-+#define TAS(lock) tas(lock)
 +/*
-+ * NOTE: per the Enhanced PowerPC Architecture manual, v1.0 dated 7-May-2002,
-+ * an isync is a sufficient synchronization barrier after a lwarx/stwcx loop.
++ * Default Definitions - override these above as needed.
 + */
-+static __inline__ int
-+tas(volatile slock_t *lock)
-+{
-+      slock_t _t;
-+      int _res;
 +
-+      __asm__ __volatile__(
-+"     lwarx   %0,0,%3         \n"
-+"     cmpwi   %0,0            \n"
-+"     bne     1f                      \n"
-+"     addi    %0,%0,1         \n"
-+"     stwcx.  %0,0,%3         \n"
-+"     beq     2f              \n"
-+"1:   li      %1,1            \n"
-+"     b               3f                      \n"
-+"2:                                           \n"
-+"     isync                           \n"
-+"     li      %1,0            \n"
-+"3:                                           \n"
++#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 1 /* -- APC: Non-blocking lock available for this case -- */
 +
-+:     "=&r"(_t), "=r"(_res), "+m"(*lock)
-+:     "r"(lock)
-+:     "memory", "cc");
-+      return _res;
-+}
++#if !defined(S_LOCK)
++#define S_LOCK(lock) \
++      do { \
++              if (TAS(lock)) \
++                      s_lock((lock), __FILE__, __LINE__); \
++      } while (0)
++#endif         /* S_LOCK */
 +
-+/* PowerPC S_UNLOCK is almost standard but requires a "sync" instruction */
-+#define S_UNLOCK(lock)        \
-+do \
-+{ \
-+      __asm__ __volatile__ (" sync \n"); \
-+      *((volatile slock_t *) (lock)) = 0; \
-+} while (0)
++#if !defined(S_LOCK_FREE)
++#define S_LOCK_FREE(lock)     (*(lock) == 0)
++#endif         /* S_LOCK_FREE */
 +
-+#endif /* powerpc */
++#if !defined(S_UNLOCK)
++#define S_UNLOCK(lock)                (*((volatile slock_t *) (lock)) = 0)
++#endif         /* S_UNLOCK */
 +
++#if !defined(S_INIT_LOCK)
++#define S_INIT_LOCK(lock)     S_UNLOCK(lock)
++#endif         /* S_INIT_LOCK */
 +
-+/* Linux Motorola 68k */
-+#if (defined(__mc68000__) || defined(__m68k__)) && defined(__linux__)
-+#define HAS_TEST_AND_SET
++#if !defined(SPIN_DELAY)
++#define SPIN_DELAY()  ((void) 0)
++#endif         /* SPIN_DELAY */
 +
-+typedef unsigned char slock_t;
++#if !defined(TAS)
++extern int    tas(volatile slock_t *lock);            /* in port/.../tas.s, or
++                                                                                               * s_lock.c */
 +
-+#define TAS(lock) tas(lock)
++#define TAS(lock)             tas(lock)
++#endif         /* TAS */
 +
-+static __inline__ int
-+tas(volatile slock_t *lock)
-+{
-+      register int rv;
 +
-+      __asm__ __volatile__(
-+              "       clrl    %0              \n"
-+              "       tas             %1              \n"
-+              "       sne             %0              \n"
-+:             "=d"(rv), "+m"(*lock)
-+:
-+:             "memory", "cc");
-+      return rv;
-+}
++/*
++ * Platform-independent out-of-line support routines
++ */
++extern void s_lock(volatile slock_t *lock, const char *file, int line);
 +
-+#endif         /* (__mc68000__ || __m68k__) && __linux__ */
++/* Support for dynamic adjustment of spins_per_delay */
++#define DEFAULT_SPINS_PER_DELAY  100
 +
++#if 0  /* -- Removed from APC use -- */
++extern void set_spins_per_delay(int shared_spins_per_delay);
++extern int    update_spins_per_delay(int shared_spins_per_delay);
++#endif
 +
++#endif         /* S_LOCK_H */
+diff -Naur php-5.3.1.orig/ext/apc/php_apc.c php-5.3.1/ext/apc/php_apc.c
+--- php-5.3.1.orig/ext/apc/php_apc.c   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/php_apc.c        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,1649 @@
 +/*
-+ * VAXen -- even multiprocessor ones
-+ * (thanks to Tom Ivar Helbekkmo)
-+ */
-+#if defined(__vax__)
-+#define HAS_TEST_AND_SET
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          Rasmus Lerdorf <rasmus@php.net>                             |
++  +----------------------------------------------------------------------+
 +
-+typedef unsigned char slock_t;
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
 +
-+#define TAS(lock) tas(lock)
++   All other licensing and usage conditions are those of the PHP Group.
 +
-+static __inline__ int
-+tas(volatile slock_t *lock)
-+{
-+      register int    _res;
++ */
 +
-+      __asm__ __volatile__(
-+              "       movl    $1, %0                  \n"
-+              "       bbssi   $0, (%2), 1f    \n"
-+              "       clrl    %0                              \n"
-+              "1: \n"
-+:             "=&r"(_res), "+m"(*lock)
-+:             "r"(lock)
-+:             "memory");
-+      return _res;
-+}
++/* $Id: php_apc.c 286798 2009-08-04 11:27:12Z gopalv $ */
 +
-+#endif         /* __vax__ */
++#include "apc_zend.h"
++#include "apc_cache.h"
++#include "apc_iterator.h"
++#include "apc_main.h"
++#include "apc_sma.h"
++#include "apc_lock.h"
++#include "apc_bin.h"
++#include "php_globals.h"
++#include "php_ini.h"
++#include "ext/standard/info.h"
++#include "ext/standard/file.h"
++#include "ext/standard/flock_compat.h"
++#ifdef HAVE_SYS_FILE_H
++#include <sys/file.h>
++#endif
++#include "SAPI.h"
++#include "rfc1867.h"
++#include "php_apc.h"
++#include "ext/standard/md5.h"
 +
++#if HAVE_SIGACTION
++#include "apc_signal.h"
++#endif
 +
-+#if defined(__ns32k__)                /* National Semiconductor 32K */
-+#define HAS_TEST_AND_SET
++/* {{{ PHP_FUNCTION declarations */
++PHP_FUNCTION(apc_cache_info);
++PHP_FUNCTION(apc_clear_cache);
++PHP_FUNCTION(apc_sma_info);
++PHP_FUNCTION(apc_store);
++PHP_FUNCTION(apc_fetch);
++PHP_FUNCTION(apc_delete);
++PHP_FUNCTION(apc_delete_file);
++PHP_FUNCTION(apc_compile_file);
++PHP_FUNCTION(apc_define_constants);
++PHP_FUNCTION(apc_load_constants);
++PHP_FUNCTION(apc_add);
++PHP_FUNCTION(apc_inc);
++PHP_FUNCTION(apc_dec);
++PHP_FUNCTION(apc_cas);
++PHP_FUNCTION(apc_bin_dump);
++PHP_FUNCTION(apc_bin_load);
++PHP_FUNCTION(apc_bin_dumpfile);
++PHP_FUNCTION(apc_bin_loadfile);
++/* }}} */
 +
-+typedef unsigned char slock_t;
++/* {{{ ZEND_DECLARE_MODULE_GLOBALS(apc) */
++ZEND_DECLARE_MODULE_GLOBALS(apc)
 +
-+#define TAS(lock) tas(lock)
++/* True globals */
++apc_cache_t* apc_cache = NULL;
++apc_cache_t* apc_user_cache = NULL;
 +
-+static __inline__ int
-+tas(volatile slock_t *lock)
++static void php_apc_init_globals(zend_apc_globals* apc_globals TSRMLS_DC)
 +{
-+      register int    _res;
-+
-+      __asm__ __volatile__(
-+              "       sbitb   0, %1   \n"
-+              "       sfsd    %0              \n"
-+:             "=r"(_res), "+m"(*lock)
-+:
-+:             "memory");
-+      return _res;
++    apc_globals->filters = NULL;
++    apc_globals->compiled_filters = NULL;
++    apc_globals->initialized = 0;
++    apc_globals->cache_stack = apc_stack_create(0);
++    apc_globals->cache_by_default = 1;
++    apc_globals->fpstat = 1;
++    apc_globals->canonicalize = 1;
++    apc_globals->stat_ctime = 0;
++    apc_globals->write_lock = 1;
++    apc_globals->report_autofilter = 0;
++    apc_globals->include_once = 0;
++    apc_globals->apc_optimize_function = NULL;
++#ifdef MULTIPART_EVENT_FORMDATA
++    apc_globals->rfc1867 = 0;
++    memset(&(apc_globals->rfc1867_data), 0, sizeof(apc_rfc1867_data));
++#endif
++    memset(&apc_globals->copied_zvals, 0, sizeof(HashTable));
++    apc_globals->force_file_update = 0;
++    apc_globals->coredump_unmap = 0;
++    apc_globals->preload_path = NULL;
++    apc_globals->use_request_time = 1;
++    apc_globals->lazy_class_table = NULL;
++    apc_globals->lazy_function_table = NULL;
 +}
 +
-+#endif         /* __ns32k__ */
++static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC)
++{
++    /* deallocate the ignore patterns */
++    if (apc_globals->filters != NULL) {
++        int i;
++        for (i=0; apc_globals->filters[i] != NULL; i++) {
++            apc_efree(apc_globals->filters[i]);
++        }
++        apc_efree(apc_globals->filters);
++    }
 +
++    /* the stack should be empty */
++    assert(apc_stack_size(apc_globals->cache_stack) == 0);
 +
-+#if defined(__alpha) || defined(__alpha__)    /* Alpha */
-+/*
-+ * Correct multi-processor locking methods are explained in section 5.5.3
-+ * of the Alpha AXP Architecture Handbook, which at this writing can be
-+ * found at ftp://ftp.netbsd.org/pub/NetBSD/misc/dec-docs/index.html.
-+ * For gcc we implement the handbook's code directly with inline assembler.
-+ */
-+#define HAS_TEST_AND_SET
++    /* apc cleanup */
++    apc_stack_destroy(apc_globals->cache_stack);
 +
-+typedef unsigned long slock_t;
++    /* the rest of the globals are cleaned up in apc_module_shutdown() */
++}
 +
-+#define TAS(lock)  tas(lock)
++/* }}} */
 +
-+static __inline__ int
-+tas(volatile slock_t *lock)
-+{
-+      register slock_t _res;
++/* {{{ PHP_INI */
 +
-+      __asm__ __volatile__(
-+              "       ldq             $0, %1  \n"
-+              "       bne             $0, 2f  \n"
-+              "       ldq_l   %0, %1  \n"
-+              "       bne             %0, 2f  \n"
-+              "       mov             1,  $0  \n"
-+              "       stq_c   $0, %1  \n"
-+              "       beq             $0, 2f  \n"
-+              "       mb                              \n"
-+              "       br              3f              \n"
-+              "2:     mov             1, %0   \n"
-+              "3:                                     \n"
-+:             "=&r"(_res), "+m"(*lock)
-+:
-+:             "memory", "0");
-+      return (int) _res;
++static PHP_INI_MH(OnUpdate_filters) /* {{{ */
++{
++    APCG(filters) = apc_tokenize(new_value, ',');
++    return SUCCESS;
 +}
++/* }}} */
 +
-+#define S_UNLOCK(lock)        \
-+do \
-+{\
-+      __asm__ __volatile__ (" mb \n"); \
-+      *((volatile slock_t *) (lock)) = 0; \
-+} while (0)
-+
-+#endif /* __alpha || __alpha__ */
++static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */
++{
++#if APC_MMAP
++    if(atoi(new_value)!=1) {
++        php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_segments setting ignored in MMAP mode");
++    }
++    APCG(shm_segments) = 1;
++#else
++    APCG(shm_segments) = atoi(new_value);
++#endif
++    return SUCCESS;
++}
++/* }}} */
 +
++#ifdef MULTIPART_EVENT_FORMDATA
++static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
++{
++    int tmp;
++    tmp = zend_atoi(new_value, new_value_length);
++    if(tmp < 0) {
++        apc_eprint("rfc1867_freq must be greater than or equal to zero.");
++        return FAILURE;
++    }
++    if(new_value[new_value_length-1] == '%') {
++        if(tmp > 100) {
++            apc_eprint("rfc1867_freq cannot be over 100%%");
++            return FAILURE;
++        }
++        APCG(rfc1867_freq) = tmp / 100.0;
++    } else {
++        APCG(rfc1867_freq) = tmp;
++    }
++    return SUCCESS;
++}
++/* }}} */
++#endif
 +
-+#if defined(__mips__) && !defined(__sgi)      /* non-SGI MIPS */
-+/* Note: on SGI we use the OS' mutex ABI, see below */
-+/* Note: R10000 processors require a separate SYNC */
-+#define HAS_TEST_AND_SET
++#define OnUpdateInt OnUpdateLong
 +
-+typedef unsigned int slock_t;
++PHP_INI_BEGIN()
++STD_PHP_INI_BOOLEAN("apc.enabled",      "1",    PHP_INI_SYSTEM, OnUpdateBool,              enabled,         zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.shm_segments",   "1",    PHP_INI_SYSTEM, OnUpdateShmSegments,       shm_segments,    zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.shm_size",       "30",   PHP_INI_SYSTEM, OnUpdateInt,            shm_size,        zend_apc_globals, apc_globals)
++STD_PHP_INI_BOOLEAN("apc.include_once_override", "0", PHP_INI_SYSTEM, OnUpdateBool,     include_once,    zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", PHP_INI_SYSTEM, OnUpdateInt,            num_files_hint,  zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.user_entries_hint", "4096", PHP_INI_SYSTEM, OnUpdateInt,          user_entries_hint, zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.gc_ttl",         "3600", PHP_INI_SYSTEM, OnUpdateInt,            gc_ttl,           zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.ttl",            "0",    PHP_INI_SYSTEM, OnUpdateInt,            ttl,              zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.user_ttl",       "0",    PHP_INI_SYSTEM, OnUpdateInt,            user_ttl,         zend_apc_globals, apc_globals)
++#if APC_MMAP
++STD_PHP_INI_ENTRY("apc.mmap_file_mask",  NULL,  PHP_INI_SYSTEM, OnUpdateString,         mmap_file_mask,   zend_apc_globals, apc_globals)
++#endif
++PHP_INI_ENTRY("apc.filters",        NULL,     PHP_INI_SYSTEM, OnUpdate_filters)
++STD_PHP_INI_BOOLEAN("apc.cache_by_default", "1",  PHP_INI_ALL, OnUpdateBool,         cache_by_default, zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.file_update_protection", "2", PHP_INI_SYSTEM, OnUpdateInt,file_update_protection,  zend_apc_globals, apc_globals)
++STD_PHP_INI_BOOLEAN("apc.enable_cli", "0",      PHP_INI_SYSTEM, OnUpdateBool,           enable_cli,       zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.max_file_size", "1M",    PHP_INI_SYSTEM, OnUpdateInt,            max_file_size,    zend_apc_globals, apc_globals)
++STD_PHP_INI_BOOLEAN("apc.stat", "1",            PHP_INI_SYSTEM, OnUpdateBool,           fpstat,           zend_apc_globals, apc_globals)
++STD_PHP_INI_BOOLEAN("apc.canonicalize", "1",    PHP_INI_SYSTEM, OnUpdateBool,           canonicalize,     zend_apc_globals, apc_globals)
++STD_PHP_INI_BOOLEAN("apc.stat_ctime", "0",      PHP_INI_SYSTEM, OnUpdateBool,           stat_ctime,       zend_apc_globals, apc_globals)
++STD_PHP_INI_BOOLEAN("apc.write_lock", "1",      PHP_INI_SYSTEM, OnUpdateBool,           write_lock,       zend_apc_globals, apc_globals)
++STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool,         report_autofilter,zend_apc_globals, apc_globals)
++#ifdef MULTIPART_EVENT_FORMDATA
++STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.rfc1867_prefix", "upload_", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_prefix, zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.rfc1867_name", "APC_UPLOAD_PROGRESS", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_name, zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.rfc1867_freq", "0", PHP_INI_SYSTEM, OnUpdateRfc1867Freq, rfc1867_freq, zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.rfc1867_ttl", "3600", PHP_INI_SYSTEM, OnUpdateInt, rfc1867_ttl, zend_apc_globals, apc_globals)
++#endif
++STD_PHP_INI_BOOLEAN("apc.coredump_unmap", "0", PHP_INI_SYSTEM, OnUpdateBool, coredump_unmap, zend_apc_globals, apc_globals)
++STD_PHP_INI_ENTRY("apc.preload_path", (char*)NULL,              PHP_INI_SYSTEM, OnUpdateString,       preload_path,  zend_apc_globals, apc_globals)
++STD_PHP_INI_BOOLEAN("apc.file_md5", "0", PHP_INI_SYSTEM, OnUpdateBool, file_md5,  zend_apc_globals, apc_globals)
++STD_PHP_INI_BOOLEAN("apc.use_request_time", "1", PHP_INI_ALL, OnUpdateBool, use_request_time,  zend_apc_globals, apc_globals)
++STD_PHP_INI_BOOLEAN("apc.lazy_functions", "0", PHP_INI_SYSTEM, OnUpdateBool, lazy_functions, zend_apc_globals, apc_globals)
++STD_PHP_INI_BOOLEAN("apc.lazy_classes", "0", PHP_INI_SYSTEM, OnUpdateBool, lazy_classes, zend_apc_globals, apc_globals)
++PHP_INI_END()
 +
-+#define TAS(lock) tas(lock)
++/* }}} */
 +
-+static __inline__ int
-+tas(volatile slock_t *lock)
++/* {{{ PHP_MINFO_FUNCTION(apc) */
++static PHP_MINFO_FUNCTION(apc)
 +{
-+      register volatile slock_t *_l = lock;
-+      register int _res;
-+      register int _tmp;
-+
-+      __asm__ __volatile__(
-+              "       .set push           \n"
-+              "       .set mips2          \n"
-+              "       .set noreorder      \n"
-+              "       .set nomacro        \n"
-+              "       ll      %0, %2      \n"
-+              "       or      %1, %0, 1   \n"
-+              "       sc      %1, %2      \n"
-+              "       xori    %1, 1       \n"
-+              "       or      %0, %0, %1  \n"
-+              "       sync                \n"
-+              "       .set pop              "
-+:             "=&r" (_res), "=&r" (_tmp), "+R" (*_l)
-+:
-+:             "memory");
-+      return _res;
++    php_info_print_table_start();
++    php_info_print_table_header(2, "APC Support", APCG(enabled) ? "enabled" : "disabled");
++    php_info_print_table_row(2, "Version", PHP_APC_VERSION);
++#if APC_MMAP
++    php_info_print_table_row(2, "MMAP Support", "Enabled");
++    php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask));
++#else
++    php_info_print_table_row(2, "MMAP Support", "Disabled");
++#endif
++    php_info_print_table_row(2, "Locking type", APC_LOCK_TYPE);
++    php_info_print_table_row(2, "Revision", "$Revision: 286798 $");
++    php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
++    php_info_print_table_end();
++    DISPLAY_INI_ENTRIES();
 +}
++/* }}} */
 +
-+/* MIPS S_UNLOCK is almost standard but requires a "sync" instruction */
-+#define S_UNLOCK(lock)        \
-+do \
-+{ \
-+      __asm__ __volatile__( \
-+              "       .set push           \n" \
-+              "       .set mips2          \n" \
-+              "       .set noreorder      \n" \
-+              "       .set nomacro        \n" \
-+              "       sync                \n" \
-+              "       .set pop              "); \
-+      *((volatile slock_t *) (lock)) = 0; \
-+} while (0)
++#ifdef MULTIPART_EVENT_FORMDATA
++extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC);
++#endif
 +
-+#endif /* __mips__ && !__sgi */
++/* {{{ PHP_MINIT_FUNCTION(apc) */
++static PHP_MINIT_FUNCTION(apc)
++{
++    ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);
 +
++    REGISTER_INI_ENTRIES();
 +
-+/* These live in s_lock.c, but only for gcc */
++    /* Disable APC in cli mode unless overridden by apc.enable_cli */
++    if(!APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) {
++        APCG(enabled) = 0;
++    }
++
++    if (APCG(enabled)) {
++        if(APCG(initialized)) {
++            apc_process_init(module_number TSRMLS_CC);
++        } else {
++            apc_module_init(module_number TSRMLS_CC);
++            apc_zend_init(TSRMLS_C);
++            apc_process_init(module_number TSRMLS_CC);
++#ifdef MULTIPART_EVENT_FORMDATA
++            /* File upload progress tracking */
++            if(APCG(rfc1867)) {
++                php_rfc1867_callback = apc_rfc1867_progress;
++            }
++#endif
++            apc_iterator_init(module_number TSRMLS_CC);
++        }
 +
++        zend_register_long_constant("APC_BIN_VERIFY_MD5", sizeof("APC_BIN_VERIFY_MD5"), APC_BIN_VERIFY_MD5, (CONST_CS | CONST_PERSISTENT), module_number TSRMLS_CC);
++        zend_register_long_constant("APC_BIN_VERIFY_CRC32", sizeof("APC_BIN_VERIFY_CRC32"), APC_BIN_VERIFY_CRC32, (CONST_CS | CONST_PERSISTENT), module_number TSRMLS_CC);
++    }
 +
-+#if defined(__m68k__) && !defined(__linux__)  /* non-Linux Motorola 68k */
-+#define HAS_TEST_AND_SET
++    return SUCCESS;
++}
++/* }}} */
 +
-+typedef unsigned char slock_t;
++/* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */
++static PHP_MSHUTDOWN_FUNCTION(apc)
++{
++    if(APCG(enabled)) {
++        apc_process_shutdown(TSRMLS_C);
++        apc_zend_shutdown(TSRMLS_C);
++        apc_module_shutdown(TSRMLS_C);
++#ifndef ZTS
++        php_apc_shutdown_globals(&apc_globals);
++#endif
++#if HAVE_SIGACTION
++        apc_shutdown_signals();
++#endif
++    }
++#ifdef ZTS
++    ts_free_id(apc_globals_id);
 +#endif
++    UNREGISTER_INI_ENTRIES();
++    return SUCCESS;
++}
++/* }}} */
 +
++/* {{{ PHP_RINIT_FUNCTION(apc) */
++static PHP_RINIT_FUNCTION(apc)
++{
++    if(APCG(enabled)) {
++        apc_request_init(TSRMLS_C);
 +
-+#endif        /* __GNUC__ */
++#if HAVE_SIGACTION
++        apc_set_signals(TSRMLS_C);
++#endif
++    }
++    return SUCCESS;
++}
++/* }}} */
 +
++/* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */
++static PHP_RSHUTDOWN_FUNCTION(apc)
++{
++    if(APCG(enabled)) {
++        apc_request_shutdown(TSRMLS_C);
++    }
++    return SUCCESS;
++}
++/* }}} */
 +
++/* {{{ proto array apc_cache_info([string type [, bool limited]]) */
++PHP_FUNCTION(apc_cache_info)
++{
++    apc_cache_info_t* info;
++    apc_cache_link_t* p;
++    zval* list;
++    char *cache_type;
++    int ct_len;
++    zend_bool limited=0;
++    char md5str[33];
 +
-+/*
-+ * ---------------------------------------------------------------------
-+ * Platforms that use non-gcc inline assembly:
-+ * ---------------------------------------------------------------------
-+ */
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) {
++        return;
++    }
 +
-+#if !defined(HAS_TEST_AND_SET)        /* We didn't trigger above, let's try here */
++    if(ZEND_NUM_ARGS()) {
++        if(!strcasecmp(cache_type,"user")) {
++            info = apc_cache_info(apc_user_cache, limited);
++        } else if(!strcasecmp(cache_type,"filehits")) {
++#ifdef APC_FILEHITS
++            RETVAL_ZVAL(APCG(filehits), 1, 0);
++            return;
++#else
++            RETURN_FALSE;
++#endif
++        } else {
++            info = apc_cache_info(apc_cache, limited);
++        }
++    } else info = apc_cache_info(apc_cache, limited);
 +
++    if(!info) {
++        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC info available.  Perhaps APC is not enabled? Check apc.enabled in your ini file");
++        RETURN_FALSE;
++    }
 +
-+#if defined(USE_UNIVEL_CC)            /* Unixware compiler */
-+#define HAS_TEST_AND_SET
++    array_init(return_value);
++    add_assoc_long(return_value, "num_slots", info->num_slots);
++    add_assoc_long(return_value, "ttl", info->ttl);
 +
-+typedef unsigned char slock_t;
++    add_assoc_double(return_value, "num_hits", (double)info->num_hits);
++    add_assoc_double(return_value, "num_misses", (double)info->num_misses);
++    add_assoc_double(return_value, "num_inserts", (double)info->num_inserts);
++    add_assoc_double(return_value, "expunges", (double)info->expunges);
++    
++    add_assoc_long(return_value, "start_time", info->start_time);
++    add_assoc_double(return_value, "mem_size", (double)info->mem_size);
++    add_assoc_long(return_value, "num_entries", info->num_entries);
++#ifdef MULTIPART_EVENT_FORMDATA
++    add_assoc_long(return_value, "file_upload_progress", 1);
++#else
++    add_assoc_long(return_value, "file_upload_progress", 0);
++#endif
++#if APC_MMAP
++    add_assoc_stringl(return_value, "memory_type", "mmap", sizeof("mmap")-1, 1);
++#else
++    add_assoc_stringl(return_value, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1);
++#endif
++#if APC_SEM_LOCKS
++    add_assoc_stringl(return_value, "locking_type", "IPC semaphore", sizeof("IPC semaphore")-1, 1);
++#elif APC_PTHREADMUTEX_LOCKS
++    add_assoc_stringl(return_value, "locking_type", "pthread mutex", sizeof("pthread mutex")-1, 1);
++#elif APC_SPIN_LOCKS
++    add_assoc_stringl(return_value, "locking_type", "spin", sizeof("spin")-1, 1);
++#else
++    add_assoc_stringl(return_value, "locking_type", "file", sizeof("file")-1, 1);
++#endif
++    if(limited) {
++        apc_cache_free_info(info);
++        return;
++    }
 +
-+#define TAS(lock)     tas(lock)
++    ALLOC_INIT_ZVAL(list);
++    array_init(list);
 +
-+asm int
-+tas(volatile slock_t *s_lock)
-+{
-+/* UNIVEL wants %mem in column 1, so we don't pg_indent this file */
-+%mem s_lock
-+      pushl %ebx
-+      movl s_lock, %ebx
-+      movl $255, %eax
-+      lock
-+      xchgb %al, (%ebx)
-+      popl %ebx
-+}
++    for (p = info->list; p != NULL; p = p->next) {
++        zval* link;
 +
-+#endif         /* defined(USE_UNIVEL_CC) */
++        ALLOC_INIT_ZVAL(link);
++        array_init(link);
 +
++        if(p->type == APC_CACHE_ENTRY_FILE) {
++            add_assoc_string(link, "filename", p->data.file.filename, 1);
++            add_assoc_long(link, "device", p->data.file.device);
++            add_assoc_long(link, "inode", p->data.file.inode);
++            add_assoc_string(link, "type", "file", 1);
++            if(APCG(file_md5)) {
++                make_digest(md5str, p->data.file.md5);
++                add_assoc_string(link, "md5", md5str, 1);
++            }
++        } else if(p->type == APC_CACHE_ENTRY_USER) {
++            add_assoc_string(link, "info", p->data.user.info, 1);
++            add_assoc_long(link, "ttl", (long)p->data.user.ttl);
++            add_assoc_string(link, "type", "user", 1);
++        }
 +
-+#if defined(__alpha) || defined(__alpha__)    /* Tru64 Unix Alpha compiler */
-+/*
-+ * The Tru64 compiler doesn't support gcc-style inline asm, but it does
-+ * have some builtin functions that accomplish much the same results.
-+ * For simplicity, slock_t is defined as long (ie, quadword) on Alpha
-+ * regardless of the compiler in use.  LOCK_LONG and UNLOCK_LONG only
-+ * operate on an int (ie, longword), but that's OK as long as we define
-+ * S_INIT_LOCK to zero out the whole quadword.
-+ */
-+#define HAS_TEST_AND_SET
++        add_assoc_double(link, "num_hits", (double)p->num_hits);
++        
++        add_assoc_long(link, "mtime", p->mtime);
++        add_assoc_long(link, "creation_time", p->creation_time);
++        add_assoc_long(link, "deletion_time", p->deletion_time);
++        add_assoc_long(link, "access_time", p->access_time);
++        add_assoc_long(link, "ref_count", p->ref_count);
++        add_assoc_long(link, "mem_size", p->mem_size);
++        
 +
-+typedef unsigned long slock_t;
++        add_next_index_zval(list, link);
++    }
++    add_assoc_zval(return_value, "cache_list", list);
 +
-+#include <alpha/builtins.h>
-+#define S_INIT_LOCK(lock)  (*(lock) = 0)
-+#define TAS(lock)                (__LOCK_LONG_RETRY((lock), 1) == 0)
-+#define S_UNLOCK(lock)           __UNLOCK_LONG(lock)
++    ALLOC_INIT_ZVAL(list);
++    array_init(list);
 +
-+#endif         /* __alpha || __alpha__ */
++    for (p = info->deleted_list; p != NULL; p = p->next) {
++        zval* link;
 +
++        ALLOC_INIT_ZVAL(link);
++        array_init(link);
 +
-+#if defined(__hppa) || defined(__hppa__)      /* HP PA-RISC, GCC and HP compilers */
-+/*
-+ * HP's PA-RISC
-+ *
-+ * See src/backend/port/hpux/tas.c.template for details about LDCWX.  Because
-+ * LDCWX requires a 16-byte-aligned address, we declare slock_t as a 16-byte
-+ * struct.  The active word in the struct is whichever has the aligned address;
-+ * the other three words just sit at -1.
-+ *
-+ * When using gcc, we can inline the required assembly code.
-+ */
-+#define HAS_TEST_AND_SET
++        if(p->type == APC_CACHE_ENTRY_FILE) {
++            add_assoc_string(link, "filename", p->data.file.filename, 1);
++            add_assoc_long(link, "device", p->data.file.device);
++            add_assoc_long(link, "inode", p->data.file.inode);
++            add_assoc_string(link, "type", "file", 1);
++            if(APCG(file_md5)) {
++                make_digest(md5str, p->data.file.md5);
++                add_assoc_string(link, "md5", md5str, 1);
++            }
++        } else if(p->type == APC_CACHE_ENTRY_USER) {
++            add_assoc_string(link, "info", p->data.user.info, 1);
++            add_assoc_long(link, "ttl", (long)p->data.user.ttl);
++            add_assoc_string(link, "type", "user", 1);
++        }
++        
++        add_assoc_double(link, "num_hits", (double)p->num_hits);
++        
++        add_assoc_long(link, "mtime", p->mtime);
++        add_assoc_long(link, "creation_time", p->creation_time);
++        add_assoc_long(link, "deletion_time", p->deletion_time);
++        add_assoc_long(link, "access_time", p->access_time);
++        add_assoc_long(link, "ref_count", p->ref_count);
++        add_assoc_long(link, "mem_size", p->mem_size);
++        add_next_index_zval(list, link);
++    }
++    add_assoc_zval(return_value, "deleted_list", list);
 +
-+typedef struct
++    apc_cache_free_info(info);
++}
++/* }}} */
++
++/* {{{ proto void apc_clear_cache([string cache]) */
++PHP_FUNCTION(apc_clear_cache)
 +{
-+      int                     sema[4];
-+} slock_t;
++    char *cache_type;
++    int ct_len = 0;
 +
-+#define TAS_ACTIVE_WORD(lock) ((volatile int *) (((long) (lock) + 15) & ~15))
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) {
++        return;
++    }
 +
-+#if defined(__GNUC__)
++    if(ct_len) {
++        if(!strcasecmp(cache_type, "user")) {
++            apc_cache_clear(apc_user_cache);
++            RETURN_TRUE;
++        }
++    }
++    apc_cache_clear(apc_cache);
++    RETURN_TRUE;
++}
++/* }}} */
 +
-+static __inline__ int
-+tas(volatile slock_t *lock)
++/* {{{ proto array apc_sma_info([bool limited]) */
++PHP_FUNCTION(apc_sma_info)
 +{
-+      volatile int *lockword = TAS_ACTIVE_WORD(lock);
-+      register int lockval;
++    apc_sma_info_t* info;
++    zval* block_lists;
++    int i;
++    zend_bool limited = 0;
 +
-+      __asm__ __volatile__(
-+              "       ldcwx   0(0,%2),%0      \n"
-+:             "=r"(lockval), "+m"(*lockword)
-+:             "r"(lockword)
-+:             "memory");
-+      return (lockval == 0);
-+}
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) {
++        return;
++    }
 +
-+#endif /* __GNUC__ */
++    info = apc_sma_info(limited);
 +
-+#define S_UNLOCK(lock)        (*TAS_ACTIVE_WORD(lock) = -1)
++    if(!info) {
++        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available.  Perhaps APC is disabled via apc.enabled?");
++        RETURN_FALSE;
++    }
 +
-+#define S_INIT_LOCK(lock) \
-+      do { \
-+              volatile slock_t *lock_ = (lock); \
-+              lock_->sema[0] = -1; \
-+              lock_->sema[1] = -1; \
-+              lock_->sema[2] = -1; \
-+              lock_->sema[3] = -1; \
-+      } while (0)
++    array_init(return_value);
++    add_assoc_long(return_value, "num_seg", info->num_seg);
++    add_assoc_double(return_value, "seg_size", (double)info->seg_size);
++    add_assoc_double(return_value, "avail_mem", (double)apc_sma_get_avail_mem());
 +
-+#define S_LOCK_FREE(lock)     (*TAS_ACTIVE_WORD(lock) != 0)
++    if(limited) {
++        apc_sma_free_info(info);
++        return;
++    }
 +
-+#endif         /* __hppa || __hppa__ */
++#if ALLOC_DISTRIBUTION
++    {
++        size_t *adist = apc_sma_get_alloc_distribution();
++        zval* list;
++        ALLOC_INIT_ZVAL(list);
++        array_init(list);
++        for(i=0; i<30; i++) {
++            add_next_index_long(list, adist[i]);
++        }
++        add_assoc_zval(return_value, "adist", list);
++    }
++#endif
++    ALLOC_INIT_ZVAL(block_lists);
++    array_init(block_lists);
 +
++    for (i = 0; i < info->num_seg; i++) {
++        apc_sma_link_t* p;
++        zval* list;
 +
-+#if defined(__hpux) && defined(__ia64) && !defined(__GNUC__)
++        ALLOC_INIT_ZVAL(list);
++        array_init(list);
 +
-+#define HAS_TEST_AND_SET
++        for (p = info->list[i]; p != NULL; p = p->next) {
++            zval* link;
 +
-+typedef unsigned int slock_t;
++            ALLOC_INIT_ZVAL(link);
++            array_init(link);
 +
-+#include <ia64/sys/inline.h>
-+#define TAS(lock) _Asm_xchg(_SZ_W, lock, 1, _LDHINT_NONE)
++            add_assoc_long(link, "size", p->size);
++            add_assoc_long(link, "offset", p->offset);
++            add_next_index_zval(list, link);
++        }
++        add_next_index_zval(block_lists, list);
++    }
++    add_assoc_zval(return_value, "block_lists", block_lists);
++    apc_sma_free_info(info);
++}
++/* }}} */
 +
-+#endif        /* HPUX on IA64, non gcc */
++/* {{{ */
++int _apc_update(char *strkey, int strkey_len, apc_cache_updater_t updater, void* data TSRMLS_DC) 
++{
++      if(!APCG(enabled)) {
++              return 0;
++      }
 +
++    HANDLE_BLOCK_INTERRUPTIONS();
++    APCG(current_cache) = apc_user_cache;
++    
++    if (!_apc_cache_user_update(apc_user_cache, strkey, strkey_len + 1, updater, data TSRMLS_CC)) {
++        HANDLE_UNBLOCK_INTERRUPTIONS();
++        return 0;
++    }
 +
-+#if defined(__sgi)    /* SGI compiler */
-+/*
-+ * SGI IRIX 5
-+ * slock_t is defined as a unsigned long. We use the standard SGI
-+ * mutex API.
-+ *
-+ * The following comment is left for historical reasons, but is probably
-+ * not a good idea since the mutex ABI is supported.
-+ *
-+ * This stuff may be supplemented in the future with Masato Kataoka's MIPS-II
-+ * assembly from his NECEWS SVR4 port, but we probably ought to retain this
-+ * for the R3000 chips out there.
-+ */
-+#define HAS_TEST_AND_SET
++    APCG(current_cache) = NULL;
++    HANDLE_UNBLOCK_INTERRUPTIONS();
 +
-+typedef unsigned long slock_t;
++    return 1;
++}
++/* }}} */
++    
++/* {{{ _apc_store */
++int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC) {
++    apc_cache_entry_t *entry;
++    apc_cache_key_t key;
++    time_t t;
++    apc_context_t ctxt={0,};
++    int ret = 1;
 +
-+#include "mutex.h"
-+#define TAS(lock)     (test_and_set(lock,1))
-+#define S_UNLOCK(lock)        (test_then_and(lock,0))
-+#define S_INIT_LOCK(lock)     (test_then_and(lock,0))
-+#define S_LOCK_FREE(lock)     (test_then_add(lock,0) == 0)
-+#endif         /* __sgi */
++    t = apc_time();
 +
++    if(!APCG(enabled)) return 0;
 +
-+#if defined(sinix)            /* Sinix */
-+/*
-+ * SINIX / Reliant UNIX
-+ * slock_t is defined as a struct abilock_t, which has a single unsigned long
-+ * member. (Basically same as SGI)
-+ */
-+#define HAS_TEST_AND_SET
++    HANDLE_BLOCK_INTERRUPTIONS();
 +
-+#include "abi_mutex.h"
-+typedef abilock_t slock_t;
++    APCG(current_cache) = apc_user_cache;
 +
-+#define TAS(lock)     (!acquire_lock(lock))
-+#define S_UNLOCK(lock)        release_lock(lock)
-+#define S_INIT_LOCK(lock)     init_lock(lock)
-+#define S_LOCK_FREE(lock)     (stat_lock(lock) == UNLOCKED)
-+#endif         /* sinix */
++    ctxt.pool = apc_pool_create(APC_SMALL_POOL, apc_sma_malloc, apc_sma_free, apc_sma_protect, apc_sma_unprotect);
++    if (!ctxt.pool) {
++        apc_wprint("Unable to allocate memory for pool.");
++        return 0;
++    }
++    ctxt.copy = APC_COPY_IN_USER;
++    ctxt.force_update = 0;
 +
++    if(!ctxt.pool) {
++        ret = 0;
++        goto nocache;
++    }
 +
-+#if defined(_AIX)     /* AIX */
-+/*
-+ * AIX (POWER)
-+ */
-+#define HAS_TEST_AND_SET
++    if (!apc_cache_make_user_key(&key, strkey, strkey_len, t)) {
++        goto freepool;
++    }
 +
-+typedef unsigned int slock_t;
++    if (apc_cache_is_last_key(apc_user_cache, &key, t)) {
++          goto freepool;
++    }
 +
-+#define TAS(lock)                     _check_lock(lock, 0, 1)
-+#define S_UNLOCK(lock)                _clear_lock(lock, 0)
-+#endif         /* _AIX */
++    if (!(entry = apc_cache_make_user_entry(strkey, strkey_len, val, &ctxt, ttl))) {
++        goto freepool;
++    }
 +
++    if (!apc_cache_user_insert(apc_user_cache, key, entry, &ctxt, t, exclusive TSRMLS_CC)) {
++freepool:
++        apc_pool_destroy(ctxt.pool);
++        ret = 0;
++    }
 +
-+#if defined (nextstep)                /* Nextstep */
-+#define HAS_TEST_AND_SET
++nocache:
 +
-+typedef struct mutex slock_t;
++    APCG(current_cache) = NULL;
 +
-+#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 0  /* -- APC: non-blocking lock not available in this case -- */
++    HANDLE_UNBLOCK_INTERRUPTIONS();
 +
-+#define S_LOCK(lock)  mutex_lock(lock)
-+#define S_UNLOCK(lock)        mutex_unlock(lock)
-+#define S_INIT_LOCK(lock)     mutex_init(lock)
-+/* For Mach, we have to delve inside the entrails of `struct mutex'.  Ick! */
-+#define S_LOCK_FREE(alock)    ((alock)->lock == 0)
-+#endif         /* nextstep */
++    return ret;
++}
++/* }}} */
++
++/* {{{ apc_store_helper(INTERNAL_FUNCTION_PARAMETERS, const int exclusive)
++ */
++static void apc_store_helper(INTERNAL_FUNCTION_PARAMETERS, const int exclusive)
++{
++    zval *key = NULL;
++    zval *val = NULL;
++    long ttl = 0L;
++    HashTable *hash;
++    HashPosition hpos;
++    zval **hentry;
++    char *hkey=NULL;
++    uint hkey_len;
++    ulong hkey_idx;
 +
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|zl", &key, &val, &ttl) == FAILURE) {
++        return;
++    }
 +
-+/* These are in s_lock.c */
++    if (!key) RETURN_FALSE;
 +
++    if (Z_TYPE_P(key) == IS_ARRAY) {
++        hash = Z_ARRVAL_P(key);
++        array_init(return_value);
++        zend_hash_internal_pointer_reset_ex(hash, &hpos);
++        while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
++            zend_hash_get_current_key_ex(hash, &hkey, &hkey_len, &hkey_idx, 0, &hpos);
++            if (hkey) {
++                /* hkey_len - 1 for consistency, because it includes '\0', while Z_STRLEN_P() doesn't */
++                if(!_apc_store(hkey, hkey_len - 1, *hentry, (unsigned int)ttl, exclusive TSRMLS_CC)) {
++                    add_assoc_long_ex(return_value, hkey, hkey_len, -1);  /* -1: insertion error */
++                }
++                hkey = NULL;
++            } else {
++                add_index_long(return_value, hkey_idx, -1);  /* -1: insertion error */
++            }
++            zend_hash_move_forward_ex(hash, &hpos);
++        }
++        return;
++    } else if (Z_TYPE_P(key) == IS_STRING) {
++        if (!val) RETURN_FALSE;
++        if(_apc_store(Z_STRVAL_P(key), Z_STRLEN_P(key), val, (unsigned int)ttl, exclusive TSRMLS_CC))
++            RETURN_TRUE;
++    } else {
++        apc_wprint("apc_store expects key parameter to be a string or an array of key/value pairs.");
++    }
 +
-+#if defined(sun3)             /* Sun3 */
-+#define HAS_TEST_AND_SET
++    RETURN_FALSE;
++}
++/* }}} */
 +
-+typedef unsigned char slock_t;
-+#endif
++/* {{{ proto int apc_store(mixed key, mixed var [, long ttl ])
++ */
++PHP_FUNCTION(apc_store) {
++    apc_store_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
++}
++/* }}} */
 +
++/* {{{ proto int apc_add(mixed key, mixed var [, long ttl ])
++ */
++PHP_FUNCTION(apc_add) {
++    apc_store_helper(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
++}
++/* }}} */
 +
-+#if defined(__sun) && (defined(__i386) || defined(__x86_64__) || defined(__sparc__) || defined(__sparc))
-+#define HAS_TEST_AND_SET
++/* {{{ inc_updater */
 +
-+#if defined(__i386) || defined(__x86_64__) || defined(__sparcv9) || defined(__sparcv8plus)
-+typedef unsigned int slock_t;
-+#else
-+typedef unsigned char slock_t;
-+#endif
++struct _inc_update_args {
++    long step;
++    long lval;
++};
 +
-+extern slock_t pg_atomic_cas(volatile slock_t *lock, slock_t with,
-+                                                                        slock_t cmp);
++static int inc_updater(apc_cache_t* cache, apc_cache_entry_t* entry, void* data) {
 +
-+#define TAS(a) (pg_atomic_cas((a), 1, 0) != 0)
-+#endif
++    struct _inc_update_args *args = (struct _inc_update_args*) data;
++    
++    zval* val = entry->data.user.val;
 +
++    if(Z_TYPE_P(val) == IS_LONG) {
++        Z_LVAL_P(val) += args->step;
++        args->lval = Z_LVAL_P(val);
++        return 1;
++    }
 +
-+#ifdef WIN32_ONLY_COMPILER
-+typedef LONG slock_t;
++    return 0;
++}
++/* }}} */
 +
-+#define HAS_TEST_AND_SET
-+#define TAS(lock) (InterlockedCompareExchange(lock, 1, 0))
++/* {{{ proto long apc_inc(string key [, long step [, bool& success]])
++ */
++PHP_FUNCTION(apc_inc) {
++    char *strkey;
++    int strkey_len;
++    struct _inc_update_args args = {1L, -1};
++    zval *success = NULL;
 +
-+#define SPIN_DELAY() spin_delay()
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz", &strkey, &strkey_len, &(args.step), &success) == FAILURE) {
++        return;
++    }
 +
-+static __forceinline void
-+spin_delay(void)
-+{
-+      /* See comment for gcc code. Same code, MASM syntax */
-+      __asm rep nop;
++    if(_apc_update(strkey, strkey_len, inc_updater, &args TSRMLS_CC)) {
++        if(success) ZVAL_TRUE(success);
++        RETURN_LONG(args.lval);
++    }
++    
++    if(success) ZVAL_FALSE(success);
++    
++    RETURN_FALSE;
 +}
++/* }}} */
 +
-+#endif
++/* {{{ proto long apc_dec(string key [, long step [, bool &success]])
++ */
++PHP_FUNCTION(apc_dec) {
++    char *strkey;
++    int strkey_len;
++    struct _inc_update_args args = {1L, -1};
++    zval *success = NULL;
 +
-+  
-+#endif        /* !defined(HAS_TEST_AND_SET) */
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|lz", &strkey, &strkey_len, &(args.step), &success) == FAILURE) {
++        return;
++    }
 +
++    args.step = args.step * -1;
 +
-+/* Blow up if we didn't have any way to do spinlocks */
-+#ifndef HAS_TEST_AND_SET
-+/* -- APC: We have better options in APC than this, that should be specified explicitly so just fail out and notify the user -- */
-+#error Spin locking is not available on your platform, please select another locking method (see ./configure --help).
-+/* #error PostgreSQL does not have native spinlock support on this platform.  To continue the compilation, rerun configure using --disable-spinlocks.  However, performance will be poor.  Please report this to pgsql-bugs@postgresql.org. */ 
-+#endif
++    if(_apc_update(strkey, strkey_len, inc_updater, &args TSRMLS_CC)) {
++        if(success) ZVAL_TRUE(success);
++        RETURN_LONG(args.lval);
++    }
++    
++    if(success) ZVAL_FALSE(success);
++    
++    RETURN_FALSE;
++}
++/* }}} */
 +
++/* {{{ cas_updater */
++static int cas_updater(apc_cache_t* cache, apc_cache_entry_t* entry, void* data) {
++    long* vals = ((long*)data);
++    long old = vals[0];
++    long new = vals[1];
++    zval* val = entry->data.user.val;
 +
-+#else /* !HAVE_SPINLOCKS */
++    if(Z_TYPE_P(val) == IS_LONG) {
++        if(Z_LVAL_P(val) == old) {
++            Z_LVAL_P(val) = new;
++            return 1;
++        }
++    }
 +
++    return 0;
++}
++/* }}} */
 +
-+/*
-+ * Fake spinlock implementation using semaphores --- slow and prone
-+ * to fall foul of kernel limits on number of semaphores, so don't use this
-+ * unless you must!  The subroutines appear in spin.c.
++/* {{{ proto int apc_cas(string key, int old, int new)
 + */
++PHP_FUNCTION(apc_cas) {
++    char *strkey;
++    int strkey_len;
++    long vals[2];
 +
-+/* -- Removed for APC
-+typedef PGSemaphoreData slock_t;
-+
-+extern bool s_lock_free_sema(volatile slock_t *lock);
-+extern void s_unlock_sema(volatile slock_t *lock);
-+extern void s_init_lock_sema(volatile slock_t *lock);
-+extern int    tas_sema(volatile slock_t *lock);
-+
-+#define S_LOCK_FREE(lock)     s_lock_free_sema(lock)
-+#define S_UNLOCK(lock)         s_unlock_sema(lock)
-+#define S_INIT_LOCK(lock)     s_init_lock_sema(lock)
-+#define TAS(lock)     tas_sema(lock)
-+*/
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll", &strkey, &strkey_len, &vals[0], &vals[1]) == FAILURE) {
++        return;
++    }
 +
-+#endif        /* HAVE_SPINLOCKS */
++    if(_apc_update(strkey, strkey_len, cas_updater, &vals TSRMLS_CC)) RETURN_TRUE;
++    RETURN_FALSE;
++}
++/* }}} */
 +
++void *apc_erealloc_wrapper(void *ptr, size_t size) {
++    return _erealloc(ptr, size, 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
++}
 +
-+/*
-+ * Default Definitions - override these above as needed.
++/* {{{ proto mixed apc_fetch(mixed key[, bool &success])
 + */
++PHP_FUNCTION(apc_fetch) {
++    zval *key;
++    zval *success = NULL;
++    HashTable *hash;
++    HashPosition hpos;
++    zval **hentry;
++    zval *result;
++    zval *result_entry;
++    char *strkey;
++    int strkey_len;
++    apc_cache_entry_t* entry;
++    time_t t;
++    apc_context_t ctxt = {0,};
 +
-+#define APC_SLOCK_NONBLOCKING_LOCK_AVAILABLE 1 /* -- APC: Non-blocking lock available for this case -- */
-+
-+#if !defined(S_LOCK)
-+#define S_LOCK(lock) \
-+      do { \
-+              if (TAS(lock)) \
-+                      s_lock((lock), __FILE__, __LINE__); \
-+      } while (0)
-+#endif         /* S_LOCK */
++    if(!APCG(enabled)) RETURN_FALSE;
 +
-+#if !defined(S_LOCK_FREE)
-+#define S_LOCK_FREE(lock)     (*(lock) == 0)
-+#endif         /* S_LOCK_FREE */
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|z", &key, &success) == FAILURE) {
++        return;
++    }
 +
-+#if !defined(S_UNLOCK)
-+#define S_UNLOCK(lock)                (*((volatile slock_t *) (lock)) = 0)
-+#endif         /* S_UNLOCK */
++    t = apc_time();
 +
-+#if !defined(S_INIT_LOCK)
-+#define S_INIT_LOCK(lock)     S_UNLOCK(lock)
-+#endif         /* S_INIT_LOCK */
++    if (success) {
++        ZVAL_BOOL(success, 0);
++    }
 +
-+#if !defined(SPIN_DELAY)
-+#define SPIN_DELAY()  ((void) 0)
-+#endif         /* SPIN_DELAY */
++    ctxt.pool = apc_pool_create(APC_UNPOOL, apc_php_malloc, apc_php_free, NULL, NULL);
++    if (!ctxt.pool) {
++        apc_wprint("Unable to allocate memory for pool.");
++        RETURN_FALSE;
++    }
++    ctxt.copy = APC_COPY_OUT_USER;
++    ctxt.force_update = 0;
 +
-+#if !defined(TAS)
-+extern int    tas(volatile slock_t *lock);            /* in port/.../tas.s, or
-+                                                                                               * s_lock.c */
++    if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
++        convert_to_string(key);
++    }
 +
-+#define TAS(lock)             tas(lock)
-+#endif         /* TAS */
++    if(Z_TYPE_P(key) == IS_STRING) {
++        strkey = Z_STRVAL_P(key);
++        strkey_len = Z_STRLEN_P(key);
++        if(!strkey_len) RETURN_FALSE;
++        entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
++        if(entry) {
++            /* deep-copy returned shm zval to emalloc'ed return_value */
++            apc_cache_fetch_zval(return_value, entry->data.user.val, &ctxt);
++            apc_cache_release(apc_user_cache, entry);
++        } else {
++            goto freepool;
++        }
++    } else if(Z_TYPE_P(key) == IS_ARRAY) {
++        hash = Z_ARRVAL_P(key);
++        MAKE_STD_ZVAL(result);
++        array_init(result); 
++        zend_hash_internal_pointer_reset_ex(hash, &hpos);
++        while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
++            if(Z_TYPE_PP(hentry) != IS_STRING) {
++                apc_wprint("apc_fetch() expects a string or array of strings.");
++                goto freepool;
++            }
++            entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t);
++            if(entry) {
++                /* deep-copy returned shm zval to emalloc'ed return_value */
++                MAKE_STD_ZVAL(result_entry);
++                apc_cache_fetch_zval(result_entry, entry->data.user.val, &ctxt);
++                apc_cache_release(apc_user_cache, entry);
++                zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
++            } /* don't set values we didn't find */
++            zend_hash_move_forward_ex(hash, &hpos);
++        }
++        RETVAL_ZVAL(result, 0, 1);
++    } else {
++        apc_wprint("apc_fetch() expects a string or array of strings.");
++freepool:
++        apc_pool_destroy(ctxt.pool);
++        RETURN_FALSE;
++    }
 +
++    if (success) {
++        ZVAL_BOOL(success, 1);
++    }
 +
-+/*
-+ * Platform-independent out-of-line support routines
-+ */
-+extern void s_lock(volatile slock_t *lock, const char *file, int line);
++    apc_pool_destroy(ctxt.pool);
++    return;
++}
++/* }}} */
 +
-+/* Support for dynamic adjustment of spins_per_delay */
-+#define DEFAULT_SPINS_PER_DELAY  100
 +
-+#if 0  /* -- Removed from APC use -- */
-+extern void set_spins_per_delay(int shared_spins_per_delay);
-+extern int    update_spins_per_delay(int shared_spins_per_delay);
-+#endif
++/* {{{ proto mixed apc_delete(mixed keys)
++ */
++PHP_FUNCTION(apc_delete) {
++    zval *keys;
 +
-+#endif         /* S_LOCK_H */
-diff -ubrN php-5.2.5-orig/ext/apc/php_apc.c php-5.2.5/ext/apc/php_apc.c
---- php-5.2.5-orig/ext/apc/php_apc.c   1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/php_apc.c        2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,991 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  +----------------------------------------------------------------------+
++    if(!APCG(enabled)) RETURN_FALSE;
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &keys) == FAILURE) {
++        return;
++    }
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++    if (Z_TYPE_P(keys) == IS_STRING) {
++        if (!Z_STRLEN_P(keys)) RETURN_FALSE;
++        if(apc_cache_user_delete(apc_user_cache, Z_STRVAL_P(keys), Z_STRLEN_P(keys) + 1)) {
++            RETURN_TRUE;
++        } else {
++            RETURN_FALSE;
++        }
++    } else if (Z_TYPE_P(keys) == IS_ARRAY) {
++        HashTable *hash = Z_ARRVAL_P(keys);
++        HashPosition hpos;
++        zval **hentry;
++        array_init(return_value);
++        zend_hash_internal_pointer_reset_ex(hash, &hpos);
++        while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
++            if(Z_TYPE_PP(hentry) != IS_STRING) {
++                apc_wprint("apc_delete() expects a string, array of strings, or APCIterator instance.");
++                add_next_index_zval(return_value, *hentry);
++                Z_ADDREF_PP(hentry);
++            } else if(apc_cache_user_delete(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1) != 1) {
++                add_next_index_zval(return_value, *hentry);
++                Z_ADDREF_PP(hentry);
++            }
++            zend_hash_move_forward_ex(hash, &hpos);
++        }
++        return;
++    } else if (Z_TYPE_P(keys) == IS_OBJECT) {
++        if (apc_iterator_delete(keys TSRMLS_CC)) {
++            RETURN_TRUE;
++        } else {
++            RETURN_FALSE;
++        }
++    } else {
++        apc_wprint("apc_delete() expects a string, array of strings, or APCIterator instance.");
++    }
++}
++/* }}} */
 +
++/* {{{ proto mixed apc_delete_file(mixed keys)
++ *       Deletes the given files from the opcode cache.  
++ *       Accepts a string, array of strings, or APCIterator object. 
++ *       Returns True/False, or for an Array an Array of failed files.
 + */
++PHP_FUNCTION(apc_delete_file) {
++    zval *keys;
 +
-+/* $Id: php_apc.c,v 3.154 2007/12/26 22:31:20 rasmus Exp $ */
-+
-+#include "apc_zend.h"
-+#include "apc_cache.h"
-+#include "apc_main.h"
-+#include "apc_sma.h"
-+#include "apc_lock.h"
-+#include "php_globals.h"
-+#include "php_ini.h"
-+#include "ext/standard/info.h"
-+#include "SAPI.h"
-+#include "rfc1867.h"
-+#include "php_apc.h"
-+#if PHP_API_VERSION <= 20020918
-+#if HAVE_APACHE
-+#ifdef APC_PHP4_STAT
-+#undef XtOffsetOf
-+#include "httpd.h"
-+#endif
-+#endif
-+#endif
++    if(!APCG(enabled)) RETURN_FALSE;
 +
-+#if HAVE_SIGACTION
-+#include "apc_signal.h"
-+#endif
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &keys) == FAILURE) {
++        return;
++    }
 +
-+/* {{{ PHP_FUNCTION declarations */
-+PHP_FUNCTION(apc_cache_info);
-+PHP_FUNCTION(apc_clear_cache);
-+PHP_FUNCTION(apc_sma_info);
-+PHP_FUNCTION(apc_store);
-+PHP_FUNCTION(apc_fetch);
-+PHP_FUNCTION(apc_delete);
-+PHP_FUNCTION(apc_compile_file);
-+PHP_FUNCTION(apc_define_constants);
-+PHP_FUNCTION(apc_load_constants);
-+PHP_FUNCTION(apc_add);
++    if (Z_TYPE_P(keys) == IS_STRING) {
++        if (!Z_STRLEN_P(keys)) RETURN_FALSE;
++        if(apc_cache_delete(apc_cache, Z_STRVAL_P(keys), Z_STRLEN_P(keys) + 1) != 1) {
++            RETURN_FALSE;
++        } else {
++            RETURN_TRUE;
++        }
++    } else if (Z_TYPE_P(keys) == IS_ARRAY) {
++        HashTable *hash = Z_ARRVAL_P(keys);
++        HashPosition hpos;
++        zval **hentry;
++        array_init(return_value);
++        zend_hash_internal_pointer_reset_ex(hash, &hpos);
++        while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
++            if(Z_TYPE_PP(hentry) != IS_STRING) {
++                apc_wprint("apc_delete_file() expects a string, array of strings, or APCIterator instance.");
++                add_next_index_zval(return_value, *hentry);
++                Z_ADDREF_PP(hentry);
++            } else if(apc_cache_delete(apc_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1) != 1) {
++                add_next_index_zval(return_value, *hentry);
++                Z_ADDREF_PP(hentry);
++            }
++            zend_hash_move_forward_ex(hash, &hpos);
++        }
++        return;
++    } else if (Z_TYPE_P(keys) == IS_OBJECT) {
++        if (apc_iterator_delete(keys TSRMLS_CC)) {
++            RETURN_TRUE;
++        } else {
++            RETURN_FALSE;
++        }
++    } else {
++        apc_wprint("apc_delete_file() expects a string, array of strings, or APCIterator instance.");
++    }
++}
 +/* }}} */
 +
-+/* {{{ ZEND_DECLARE_MODULE_GLOBALS(apc) */
-+ZEND_DECLARE_MODULE_GLOBALS(apc)
++static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) {
++    char *const_key;
++    unsigned int const_key_len;
++    zval **entry;
++    HashPosition pos;
 +
-+/* True globals */
-+apc_cache_t* apc_cache = NULL;       
-+apc_cache_t* apc_user_cache = NULL;
-+void* apc_compiled_filters = NULL;
++    zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(constants), &pos);
++    while (zend_hash_get_current_data_ex(Z_ARRVAL_P(constants), (void**)&entry, &pos) == SUCCESS) {
++        zend_constant c;
++        int key_type;
++        ulong num_key;
 +
-+static void php_apc_init_globals(zend_apc_globals* apc_globals TSRMLS_DC)
-+{
-+    apc_globals->filters = NULL;
-+    apc_globals->initialized = 0;
-+    apc_globals->cache_stack = apc_stack_create(0);
-+    apc_globals->cache_by_default = 1;
-+    apc_globals->slam_defense = 0;
-+    apc_globals->mem_size_ptr = NULL;
-+    apc_globals->fpstat = 1;
-+    apc_globals->stat_ctime = 0;
-+    apc_globals->write_lock = 1;
-+    apc_globals->report_autofilter = 0;
-+    apc_globals->apc_optimize_function = NULL;
-+#ifdef MULTIPART_EVENT_FORMDATA
-+    apc_globals->rfc1867 = 0;
-+#endif
-+    apc_globals->copied_zvals = NULL;
-+#ifdef ZEND_ENGINE_2
-+    apc_globals->reserved_offset = -1;
-+#endif
-+    apc_globals->localcache = 0;
-+    apc_globals->localcache_size = 0;
-+    apc_globals->lcache = NULL;
-+    apc_globals->force_file_update = 0;
-+    apc_globals->coredump_unmap = 0;
++        key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(constants), &const_key, &const_key_len, &num_key, 0, &pos);
++        if(key_type != HASH_KEY_IS_STRING) {
++            zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
++            continue;
++        }
++        switch(Z_TYPE_PP(entry)) {
++            case IS_LONG:
++            case IS_DOUBLE:
++            case IS_STRING:
++            case IS_BOOL:
++            case IS_RESOURCE:
++            case IS_NULL:
++                break;
++            default:
++                zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
++                continue;
++        }
++        c.value = **entry;
++        zval_copy_ctor(&c.value);
++        c.flags = case_sensitive;
++        c.name = zend_strndup(const_key, const_key_len);
++        c.name_len = const_key_len;
++        c.module_number = PHP_USER_CONSTANT;
++        zend_register_constant(&c TSRMLS_CC);
++
++        zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
++    }
 +}
 +
-+static void php_apc_shutdown_globals(zend_apc_globals* apc_globals TSRMLS_DC)
-+{
-+    /* deallocate the ignore patterns */
-+    if (apc_globals->filters != NULL) {
-+        int i;
-+        for (i=0; apc_globals->filters[i] != NULL; i++) {
-+            apc_efree(apc_globals->filters[i]);
-+        }
-+        apc_efree(apc_globals->filters);
++/* {{{ proto mixed apc_define_constants(string key, array constants [, bool case_sensitive])
++ */
++PHP_FUNCTION(apc_define_constants) {
++    char *strkey;
++    int strkey_len;
++    zval *constants = NULL;
++    zend_bool case_sensitive = 1;
++    int argc = ZEND_NUM_ARGS();
++
++    if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) {
++        return;
 +    }
 +
-+    /* the stack should be empty */
-+    assert(apc_stack_size(apc_globals->cache_stack) == 0); 
++    if(!strkey_len) RETURN_FALSE;
 +
-+    /* apc cleanup */
-+    apc_stack_destroy(apc_globals->cache_stack);
++    _apc_define_constants(constants, case_sensitive TSRMLS_CC);
++    if(_apc_store(strkey, strkey_len, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE;
++    RETURN_FALSE;
++} /* }}} */
 +
-+    /* the rest of the globals are cleaned up in apc_module_shutdown() */
-+}
++/* {{{ proto mixed apc_load_constants(string key [, bool case_sensitive])
++ */
++PHP_FUNCTION(apc_load_constants) {
++    char *strkey;
++    int strkey_len;
++    apc_cache_entry_t* entry;
++    time_t t;
++    zend_bool case_sensitive = 1;
 +
-+/* }}} */
++    if(!APCG(enabled)) RETURN_FALSE;
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) {
++        return;
++    }
 +
-+/* {{{ PHP_INI */
++    if(!strkey_len) RETURN_FALSE;
 +
-+static PHP_INI_MH(OnUpdate_filters) /* {{{ */
-+{
-+    APCG(filters) = apc_tokenize(new_value, ',');
-+    return SUCCESS;
-+}
-+/* }}} */
++    t = apc_time();
 +
-+static PHP_INI_MH(OnUpdateShmSegments) /* {{{ */
-+{
-+#if APC_MMAP
-+    if(atoi(new_value)!=1) {
-+        php_error_docref(NULL TSRMLS_CC, E_WARNING, "apc.shm_segments setting ignored in MMAP mode");
++    entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
++
++    if(entry) {
++        _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC);
++        apc_cache_release(apc_user_cache, entry);
++        RETURN_TRUE;
++    } else {
++        RETURN_FALSE;
 +    }
-+    APCG(shm_segments) = 1; 
-+#else
-+    APCG(shm_segments) = atoi(new_value);
-+#endif
-+    return SUCCESS;
 +}
 +/* }}} */
 +
-+#ifdef MULTIPART_EVENT_FORMDATA
-+static PHP_INI_MH(OnUpdateRfc1867Freq) /* {{{ */
-+{
-+    int tmp;
-+    tmp = zend_atoi(new_value, new_value_length);
-+    if(tmp < 0) {
-+        apc_eprint("rfc1867_freq must be greater than or equal to zero.");
-+        return FAILURE;
++/* {{{ proto mixed apc_compile_file(mixed filenames [, bool atomic])
++ */
++PHP_FUNCTION(apc_compile_file) {
++    zval *file;
++    zend_file_handle file_handle;
++    zend_op_array *op_array;
++    char** filters = NULL;
++    zend_bool cache_by_default = 1;
++    HashTable cg_function_table, cg_class_table;
++    HashTable *cg_orig_function_table, *cg_orig_class_table, *eg_orig_function_table, *eg_orig_class_table;
++    apc_cache_entry_t** cache_entries;
++    apc_cache_key_t* keys;
++    zend_op_array **op_arrays;
++    time_t t;
++    zval **hentry;
++    HashPosition hpos;
++    int i=0, c=0;
++    int *rval=NULL;
++    int count=0;
++    zend_bool atomic=1;
++    apc_context_t ctxt = {0,};
++    zend_execute_data *orig_current_execute_data;
++    int atomic_fail;
++
++    if(!APCG(enabled)) RETURN_FALSE;
++
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &file, &atomic) == FAILURE) {
++        return;
 +    }
-+    if(new_value[new_value_length-1] == '%') {
-+        if(tmp > 100) {
-+            apc_eprint("rfc1867_freq cannot be over 100%%");
-+            return FAILURE;
-+        }
-+        APCG(rfc1867_freq) = tmp / 100.0;
-+    } else {
-+        APCG(rfc1867_freq) = tmp;
++
++    if (Z_TYPE_P(file) != IS_ARRAY && Z_TYPE_P(file) != IS_STRING) {
++        apc_wprint("apc_compile_file argument must be a string or an array of strings");
++        RETURN_FALSE;
 +    }
-+    return SUCCESS;
-+}
-+/* }}} */
-+#endif
 +
-+#ifdef ZEND_ENGINE_2
-+#define OnUpdateInt OnUpdateLong
-+#endif
++    HANDLE_BLOCK_INTERRUPTIONS();
++    APCG(current_cache) = apc_cache;
 +
-+PHP_INI_BEGIN()
-+STD_PHP_INI_BOOLEAN("apc.enabled",      "1",    PHP_INI_SYSTEM, OnUpdateBool,              enabled,         zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.shm_segments",   "1",    PHP_INI_SYSTEM, OnUpdateShmSegments,       shm_segments,    zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.shm_size",       "30",   PHP_INI_SYSTEM, OnUpdateInt,            shm_size,        zend_apc_globals, apc_globals)
-+STD_PHP_INI_BOOLEAN("apc.include_once_override", "0", PHP_INI_SYSTEM, OnUpdateBool,     include_once,    zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.num_files_hint", "1000", PHP_INI_SYSTEM, OnUpdateInt,            num_files_hint,  zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.user_entries_hint", "4096", PHP_INI_SYSTEM, OnUpdateInt,          user_entries_hint, zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.gc_ttl",         "3600", PHP_INI_SYSTEM, OnUpdateInt,            gc_ttl,           zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.ttl",            "0",    PHP_INI_SYSTEM, OnUpdateInt,            ttl,              zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.user_ttl",       "0",    PHP_INI_SYSTEM, OnUpdateInt,            user_ttl,         zend_apc_globals, apc_globals)
-+#if APC_MMAP
-+STD_PHP_INI_ENTRY("apc.mmap_file_mask",  NULL,  PHP_INI_SYSTEM, OnUpdateString,         mmap_file_mask,   zend_apc_globals, apc_globals)
-+#endif
-+PHP_INI_ENTRY("apc.filters",        NULL,     PHP_INI_SYSTEM, OnUpdate_filters)
-+STD_PHP_INI_BOOLEAN("apc.cache_by_default", "1",  PHP_INI_ALL, OnUpdateBool,         cache_by_default, zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.slam_defense", "0",      PHP_INI_SYSTEM, OnUpdateInt,            slam_defense,     zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.file_update_protection", "2", PHP_INI_SYSTEM, OnUpdateInt,file_update_protection,  zend_apc_globals, apc_globals)
-+STD_PHP_INI_BOOLEAN("apc.enable_cli", "0",      PHP_INI_SYSTEM, OnUpdateBool,           enable_cli,       zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.max_file_size", "1M",    PHP_INI_SYSTEM, OnUpdateInt,            max_file_size,    zend_apc_globals, apc_globals)
-+STD_PHP_INI_BOOLEAN("apc.stat", "1",            PHP_INI_SYSTEM, OnUpdateBool,           fpstat,           zend_apc_globals, apc_globals)
-+STD_PHP_INI_BOOLEAN("apc.stat_ctime", "0",      PHP_INI_SYSTEM, OnUpdateBool,           stat_ctime,       zend_apc_globals, apc_globals)
-+STD_PHP_INI_BOOLEAN("apc.write_lock", "1",      PHP_INI_SYSTEM, OnUpdateBool,           write_lock,       zend_apc_globals, apc_globals)
-+STD_PHP_INI_BOOLEAN("apc.report_autofilter", "0", PHP_INI_SYSTEM, OnUpdateBool,         report_autofilter,zend_apc_globals, apc_globals)
-+#ifdef MULTIPART_EVENT_FORMDATA
-+STD_PHP_INI_BOOLEAN("apc.rfc1867", "0", PHP_INI_SYSTEM, OnUpdateBool, rfc1867, zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.rfc1867_prefix", "upload_", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_prefix, zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.rfc1867_name", "APC_UPLOAD_PROGRESS", PHP_INI_SYSTEM, OnUpdateStringUnempty, rfc1867_name, zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.rfc1867_freq", "0", PHP_INI_SYSTEM, OnUpdateRfc1867Freq, rfc1867_freq, zend_apc_globals, apc_globals)
-+#endif
-+STD_PHP_INI_BOOLEAN("apc.localcache", "0", PHP_INI_SYSTEM, OnUpdateBool, localcache, zend_apc_globals, apc_globals)
-+STD_PHP_INI_ENTRY("apc.localcache.size", "512", PHP_INI_SYSTEM, OnUpdateInt, localcache_size,  zend_apc_globals, apc_globals)
-+STD_PHP_INI_BOOLEAN("apc.coredump_unmap", "0", PHP_INI_SYSTEM, OnUpdateBool, coredump_unmap, zend_apc_globals, apc_globals)
-+PHP_INI_END()
++    /* reset filters and cache_by_default */
++    filters = APCG(filters);
++    APCG(filters) = NULL;
++
++    cache_by_default = APCG(cache_by_default);
++    APCG(cache_by_default) = 1;
++
++    /* Replace function/class tables to avoid namespace conflicts */
++    zend_hash_init_ex(&cg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
++    cg_orig_function_table = CG(function_table);
++    CG(function_table) = &cg_function_table;
++    zend_hash_init_ex(&cg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
++    cg_orig_class_table = CG(class_table);
++    CG(class_table) = &cg_class_table;
++    eg_orig_function_table = EG(function_table);
++    EG(function_table) = CG(function_table);
++    eg_orig_class_table = EG(class_table);
++    EG(class_table) = CG(class_table);
++    APCG(force_file_update) = 1;
 +
-+/* }}} */
++    /* Compile the file(s), loading it into the cache */
++    if (Z_TYPE_P(file) == IS_STRING) {
++        file_handle.type = ZEND_HANDLE_FILENAME;
++        file_handle.filename = Z_STRVAL_P(file);
++        file_handle.free_filename = 0;
++        file_handle.opened_path = NULL;
++
++        orig_current_execute_data = EG(current_execute_data);
++        zend_try {
++            op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
++        } zend_catch {
++            EG(current_execute_data) = orig_current_execute_data;
++            EG(in_execution) = 1;
++            CG(unclean_shutdown) = 0;
++            apc_wprint("Error compiling %s in apc_compile_file.", file_handle.filename);
++            op_array = NULL;
++        } zend_end_try();
++        if(op_array != NULL) {
++            /* Free up everything */
++            destroy_op_array(op_array TSRMLS_CC);
++            efree(op_array);
++            RETVAL_TRUE;
++        } else {
++            RETVAL_FALSE;
++        }
++        zend_destroy_file_handle(&file_handle TSRMLS_CC);
 +
-+/* {{{ PHP_MINFO_FUNCTION(apc) */
-+static PHP_MINFO_FUNCTION(apc)
-+{
-+    php_info_print_table_start();
-+    php_info_print_table_row(2, "APC Support", APCG(enabled) ? "enabled" : "disabled");
-+    php_info_print_table_row(2, "Version", APC_VERSION);
-+#if APC_MMAP
-+    php_info_print_table_row(2, "MMAP Support", "Enabled");
-+    php_info_print_table_row(2, "MMAP File Mask", APCG(mmap_file_mask));
-+#else
-+    php_info_print_table_row(2, "MMAP Support", "Disabled");
-+#endif
-+#if APC_SEM_LOCKS
-+    php_info_print_table_row(2, "Locking type", "IPC Semaphore");
-+#elif APC_FUTEX_LOCKS
-+    php_info_print_table_row(2, "Locking type", "Linux Futex Locks");
-+#elif APC_PTHREADMUTEX_LOCKS
-+    php_info_print_table_row(2, "Locking type", "pthread mutex Locks");
-+#elif APC_SPIN_LOCKS
-+    php_info_print_table_row(2, "Locking type", "spin Locks");
-+#else
-+    php_info_print_table_row(2, "Locking type", "File Locks");
-+#endif
-+    php_info_print_table_row(2, "Revision", "$Revision: 3.154 $");
-+    php_info_print_table_row(2, "Build Date", __DATE__ " " __TIME__);
-+    php_info_print_table_end();
-+    DISPLAY_INI_ENTRIES();
-+}
-+/* }}} */
++    } else { /* IS_ARRAY */
 +
-+#ifdef MULTIPART_EVENT_FORMDATA
-+extern int apc_rfc1867_progress(unsigned int event, void *event_data, void **extra TSRMLS_DC);
-+#endif
++        array_init(return_value);
 +
-+/* {{{ PHP_MINIT_FUNCTION(apc) */
-+static PHP_MINIT_FUNCTION(apc)
-+{
-+    ZEND_INIT_MODULE_GLOBALS(apc, php_apc_init_globals, php_apc_shutdown_globals);
++        t = apc_time();
 +
-+    REGISTER_INI_ENTRIES();
++        op_arrays = ecalloc(Z_ARRVAL_P(file)->nNumOfElements, sizeof(zend_op_array*));
++        cache_entries = ecalloc(Z_ARRVAL_P(file)->nNumOfElements, sizeof(apc_cache_entry_t*));
++        keys = ecalloc(Z_ARRVAL_P(file)->nNumOfElements, sizeof(apc_cache_key_t));
++        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(file), &hpos);
++        while(zend_hash_get_current_data_ex(Z_ARRVAL_P(file), (void**)&hentry, &hpos) == SUCCESS) {
++            if (Z_TYPE_PP(hentry) != IS_STRING) {
++                apc_wprint("apc_compile_file array values must be strings, aborting.");
++                break;
++            }
++            file_handle.type = ZEND_HANDLE_FILENAME;
++            file_handle.filename = Z_STRVAL_PP(hentry);
++            file_handle.free_filename = 0;
++            file_handle.opened_path = NULL;
++
++            if (!apc_cache_make_file_key(&(keys[i]), file_handle.filename, PG(include_path), t TSRMLS_CC)) {
++                add_assoc_long(return_value, Z_STRVAL_PP(hentry), -1);  /* -1: compilation error */
++                apc_wprint("Error compiling %s in apc_compile_file.", file_handle.filename);
++                break;
++            }
 +
-+    /* Disable APC in cli mode unless overridden by apc.enable_cli */
-+    if(!APCG(enable_cli) && !strcmp(sapi_module.name, "cli")) {
-+        APCG(enabled) = 0;
-+    }
++            if (keys[i].type == APC_CACHE_KEY_FPFILE) {
++                keys[i].data.fpfile.fullpath = estrndup(keys[i].data.fpfile.fullpath, keys[i].data.fpfile.fullpath_len);
++            } else if (keys[i].type == APC_CACHE_KEY_USER) {
++                keys[i].data.user.identifier = estrndup(keys[i].data.user.identifier, keys[i].data.user.identifier_len);
++            }
 +
-+    if (APCG(enabled)) {
-+        if(APCG(initialized)) {
-+            apc_process_init(module_number TSRMLS_CC);
++            orig_current_execute_data = EG(current_execute_data);
++            zend_try {
++                if (apc_compile_cache_entry(keys[i], &file_handle, ZEND_INCLUDE, t, &op_arrays[i], &cache_entries[i] TSRMLS_CC) != SUCCESS) {
++                    op_arrays[i] = NULL;
++                    cache_entries[i] = NULL;
++                    add_assoc_long(return_value, Z_STRVAL_PP(hentry), -2);  /* -2: input or cache insertion error */
++                    apc_wprint("Error compiling %s in apc_compile_file.", file_handle.filename);
++                }
++            } zend_catch {
++                EG(current_execute_data) = orig_current_execute_data;
++                EG(in_execution) = 1;
++                CG(unclean_shutdown) = 0;
++                op_arrays[i] = NULL;
++                cache_entries[i] = NULL;
++                add_assoc_long(return_value, Z_STRVAL_PP(hentry), -1);  /* -1: compilation error */
++                apc_wprint("Error compiling %s in apc_compile_file.", file_handle.filename);
++            } zend_end_try();
++
++            zend_destroy_file_handle(&file_handle TSRMLS_CC);
++            if(op_arrays[i] != NULL) {
++                count++;
++            }
++
++            /* clean out the function/class tables */
++            zend_hash_clean(&cg_function_table);
++            zend_hash_clean(&cg_class_table);
++
++            zend_hash_move_forward_ex(Z_ARRVAL_P(file), &hpos);
++            i++;
++        }
++
++        /* atomically update the cache if no errors or not atomic */
++        ctxt.copy = APC_COPY_IN_OPCODE;
++        ctxt.force_update = 1;
++        if (count == i || !atomic) {
++            rval = apc_cache_insert_mult(apc_cache, keys, cache_entries, &ctxt, t, i);
++            atomic_fail = 0;
 +        } else {
-+            apc_module_init(module_number TSRMLS_CC);
-+            apc_zend_init(TSRMLS_C);
-+            apc_process_init(module_number TSRMLS_CC);
-+#ifdef MULTIPART_EVENT_FORMDATA
-+            /* File upload progress tracking */
-+            if(APCG(rfc1867)) {
-+                php_rfc1867_callback = apc_rfc1867_progress;
++            atomic_fail = 1;
++        }
++
++        zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(file), &hpos);
++        for(c=0; c < i; c++) {
++            zend_hash_get_current_data_ex(Z_ARRVAL_P(file), (void**)&hentry, &hpos);
++            if (rval && rval[c] != 1) {
++                add_assoc_long(return_value, Z_STRVAL_PP(hentry), -2);  /* -2: input or cache insertion error */
++                if (cache_entries[c]) {
++                    apc_pool_destroy(cache_entries[c]->pool);
++                }
 +            }
-+#endif
++            if (op_arrays[c]) {
++                destroy_op_array(op_arrays[c] TSRMLS_CC);
++                efree(op_arrays[c]);
++            }
++            if (atomic_fail && cache_entries[c]) {
++                apc_pool_destroy(cache_entries[c]->pool);
++            }
++            if (keys[c].type == APC_CACHE_KEY_FPFILE) {
++                efree((void*)keys[c].data.fpfile.fullpath);
++            } else if (keys[c].type == APC_CACHE_KEY_USER) {
++                efree((void*)keys[c].data.user.identifier);
++            }
++            zend_hash_move_forward_ex(Z_ARRVAL_P(file), &hpos);
++        }
++        efree(op_arrays);
++        efree(keys);
++        efree(cache_entries);
++        if (rval) {
++            efree(rval);
 +        }
++
 +    }
 +
-+    return SUCCESS;
++    /* Return class/function tables to previous states, destroy temp tables */
++    APCG(force_file_update) = 0;
++    CG(function_table) = cg_orig_function_table;
++    zend_hash_destroy(&cg_function_table);
++    CG(class_table) = cg_orig_class_table;
++    zend_hash_destroy(&cg_class_table);
++    EG(function_table) = eg_orig_function_table;
++    EG(class_table) = eg_orig_class_table;
++
++    /* Restore global settings */
++    APCG(filters) = filters;
++    APCG(cache_by_default) = cache_by_default;
++
++    APCG(current_cache) = NULL;
++    HANDLE_UNBLOCK_INTERRUPTIONS();
++
 +}
 +/* }}} */
 +
-+/* {{{ PHP_MSHUTDOWN_FUNCTION(apc) */
-+static PHP_MSHUTDOWN_FUNCTION(apc)
-+{
-+    if(APCG(enabled)) {
-+        apc_process_shutdown(TSRMLS_C);
-+        apc_zend_shutdown(TSRMLS_C);
-+        apc_module_shutdown(TSRMLS_C);
-+#ifndef ZTS
-+        php_apc_shutdown_globals(&apc_globals);
-+#endif
++/* {{{ proto mixed apc_bin_dump([array files [, array user_vars]])
++    Returns a binary dump of the given files and user variables from the APC cache.
++    A NULL for files or user_vars signals a dump of every entry, while array() will dump nothing.
++ */
++PHP_FUNCTION(apc_bin_dump) {
++
++    zval *z_files, *z_user_vars;
++    HashTable *h_files, *h_user_vars;
++    apc_bd_t *bd;
++
++    if(!APCG(enabled)) {
++        apc_wprint("APC is not enabled, apc_bin_dump not available.");
++        RETURN_FALSE;
 +    }
-+#ifdef ZTS
-+    ts_free_id(apc_globals_id);
-+#endif
-+    UNREGISTER_INI_ENTRIES();
-+    return SUCCESS;
-+}
-+/* }}} */
 +
-+/* {{{ PHP_RINIT_FUNCTION(apc) */
-+static PHP_RINIT_FUNCTION(apc)
-+{
-+    if(APCG(enabled)) {
-+        apc_request_init(TSRMLS_C);
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!a!", &z_files, &z_user_vars) == FAILURE) {
++        return;
++    }
 +
-+#if HAVE_SIGACTION
-+        apc_set_signals();
-+#endif
++    h_files = z_files ? Z_ARRVAL_P(z_files) : NULL;
++    h_user_vars = z_user_vars ? Z_ARRVAL_P(z_user_vars) : NULL;
++    bd = apc_bin_dump(h_files, h_user_vars TSRMLS_CC);
++    if(bd) {
++        RETVAL_STRINGL((char*)bd, bd->size-1, 0);
++    } else {
++        apc_eprint("Unkown error encounterd during apc_bin_dump.");
++        RETVAL_NULL();
 +    }
-+    return SUCCESS;
++
++    return;
 +}
-+/* }}} */
 +
-+/* {{{ PHP_RSHUTDOWN_FUNCTION(apc) */
-+static PHP_RSHUTDOWN_FUNCTION(apc)
-+{
-+    if(APCG(enabled)) {
-+        apc_request_shutdown(TSRMLS_C);
++/* {{{ proto mixed apc_bin_dumpfile(array files, array user_vars, string filename, [int flags [, resource context]])
++    Output a binary dump of the given files and user variables from the APC cache to the named file.
++ */
++PHP_FUNCTION(apc_bin_dumpfile) {
++
++    zval *z_files, *z_user_vars;
++    HashTable *h_files, *h_user_vars;
++    char *filename;
++    int filename_len;
++    long flags=0;
++    zval *zcontext = NULL;
++    php_stream_context *context = NULL;
++    php_stream *stream;
++    int numbytes = 0;
++    apc_bd_t *bd;
++
++    if(!APCG(enabled)) {
++        apc_wprint("APC is not enabled, apc_bin_dumpfile not available.");
++        RETURN_FALSE;
 +    }
-+    return SUCCESS;
-+}
-+/* }}} */
 +
-+/* {{{ proto array apc_cache_info([string type] [, bool limited]) */
-+PHP_FUNCTION(apc_cache_info)
-+{
-+    apc_cache_info_t* info;
-+    apc_cache_link_t* p;
-+    zval* list;
-+    char *cache_type;
-+    int ct_len;
-+    zend_bool limited=0;
 +
-+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|sb", &cache_type, &ct_len, &limited) == FAILURE) {
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a!a!s|lr!", &z_files, &z_user_vars, &filename, &filename_len, &flags, &zcontext) == FAILURE) {
 +        return;
 +    }
 +
-+    if(ZEND_NUM_ARGS()) {
-+        if(!strcasecmp(cache_type,"user")) {
-+            info = apc_cache_info(apc_user_cache, limited);
-+        } else if(!strcasecmp(cache_type,"filehits")) {
-+#ifdef APC_FILEHITS
-+            RETVAL_ZVAL(APCG(filehits), 1, 0);
-+            return;
-+#else
-+            RETURN_FALSE;
-+#endif
-+        } else {
-+            info = apc_cache_info(apc_cache, limited);
-+        }
-+    } else info = apc_cache_info(apc_cache, limited);
-+
-+    if(!info) {
-+        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC info available.  Perhaps APC is not enabled? Check apc.enabled in your ini file");
++    if(!filename_len) {
++        apc_eprint("apc_bin_dumpfile filename argument must be a valid filename.");
 +        RETURN_FALSE;
 +    }
 +
-+    array_init(return_value);
-+    add_assoc_long(return_value, "num_slots", info->num_slots);
-+    add_assoc_long(return_value, "ttl", info->ttl);
-+    add_assoc_long(return_value, "num_hits", info->num_hits);
-+    add_assoc_long(return_value, "num_misses", info->num_misses);
-+    add_assoc_long(return_value, "start_time", info->start_time);
-+    add_assoc_long(return_value, "expunges", info->expunges);
-+    add_assoc_long(return_value, "mem_size", info->mem_size);
-+    add_assoc_long(return_value, "num_entries", info->num_entries);
-+    add_assoc_long(return_value, "num_inserts", info->num_inserts);
-+#ifdef MULTIPART_EVENT_FORMDATA
-+    add_assoc_long(return_value, "file_upload_progress", 1);
-+#else
-+    add_assoc_long(return_value, "file_upload_progress", 0);
-+#endif
-+#if APC_MMAP
-+    add_assoc_stringl(return_value, "memory_type", "mmap", sizeof("mmap")-1, 1);
-+#else
-+    add_assoc_stringl(return_value, "memory_type", "IPC shared", sizeof("IPC shared")-1, 1);
-+#endif
-+#if APC_SEM_LOCKS
-+    add_assoc_stringl(return_value, "locking_type", "IPC semaphore", sizeof("IPC semaphore")-1, 1);
-+#elif APC_FUTEX_LOCKS
-+    add_assoc_stringl(return_value, "locking_type", "Linux Futex", sizeof("Linux Futex")-1, 1);
-+#elif APC_PTHREADMUTEX_LOCKS
-+    add_assoc_stringl(return_value, "locking_type", "pthread mutex", sizeof("pthread mutex")-1, 1);
-+#elif APC_SPIN_LOCKS
-+    add_assoc_stringl(return_value, "locking_type", "spin", sizeof("spin")-1, 1);
-+#else
-+    add_assoc_stringl(return_value, "locking_type", "file", sizeof("file")-1, 1);
-+#endif
-+    if(limited) {
-+        apc_cache_free_info(info);
-+        return;
++    h_files = z_files ? Z_ARRVAL_P(z_files) : NULL;
++    h_user_vars = z_user_vars ? Z_ARRVAL_P(z_user_vars) : NULL;
++    bd = apc_bin_dump(h_files, h_user_vars TSRMLS_CC);
++    if(!bd) {
++        apc_eprint("Unkown error uncountered during apc binary dump.");
++        RETURN_FALSE;
 +    }
-+    
-+    ALLOC_INIT_ZVAL(list);
-+    array_init(list);
 +
-+    for (p = info->list; p != NULL; p = p->next) {
-+        zval* link;
 +
-+        ALLOC_INIT_ZVAL(link);
-+        array_init(link);
++    /* Most of the following has been taken from the file_get/put_contents functions */
 +
-+        if(p->type == APC_CACHE_ENTRY_FILE) {
-+            add_assoc_string(link, "filename", p->data.file.filename, 1);
-+            add_assoc_long(link, "device", p->data.file.device);
-+            add_assoc_long(link, "inode", p->data.file.inode);
-+            add_assoc_string(link, "type", "file", 1);
-+        } else if(p->type == APC_CACHE_ENTRY_USER) {
-+            add_assoc_string(link, "info", p->data.user.info, 1);
-+            add_assoc_long(link, "ttl", (long)p->data.user.ttl);
-+            add_assoc_string(link, "type", "user", 1);
-+        }
-+        add_assoc_long(link, "num_hits", p->num_hits);
-+        add_assoc_long(link, "mtime", p->mtime);
-+        add_assoc_long(link, "creation_time", p->creation_time);
-+        add_assoc_long(link, "deletion_time", p->deletion_time);
-+        add_assoc_long(link, "access_time", p->access_time);
-+        add_assoc_long(link, "ref_count", p->ref_count);
-+        add_assoc_long(link, "mem_size", p->mem_size);
-+        add_next_index_zval(list, link);
++    context = php_stream_context_from_zval(zcontext, flags & PHP_FILE_NO_DEFAULT_CONTEXT);
++    stream = php_stream_open_wrapper_ex(filename, (flags & PHP_FILE_APPEND) ? "ab" : "wb",
++                                            ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
++    if (stream == NULL) {
++        efree(bd);
++        apc_eprint("Unable to write to file in apc_bin_dumpfile.");
++        RETURN_FALSE;
 +    }
-+    add_assoc_zval(return_value, "cache_list", list);
 +
-+    ALLOC_INIT_ZVAL(list);
-+    array_init(list);
++    if (flags & LOCK_EX && php_stream_lock(stream, LOCK_EX)) {
++        php_stream_close(stream);
++        efree(bd);
++        apc_eprint("Unable to get a lock on file in apc_bin_dumpfile.");
++        RETURN_FALSE;
++    }
 +
-+    for (p = info->deleted_list; p != NULL; p = p->next) {
-+        zval* link;
++    numbytes = php_stream_write(stream, (char*)bd, bd->size);
++    if(numbytes != bd->size) {
++        numbytes = -1;
++    }
 +
-+        ALLOC_INIT_ZVAL(link);
-+        array_init(link);
++    php_stream_close(stream);
++    efree(bd);
 +
-+        if(p->type == APC_CACHE_ENTRY_FILE) {
-+            add_assoc_string(link, "filename", p->data.file.filename, 1);
-+            add_assoc_long(link, "device", p->data.file.device);
-+            add_assoc_long(link, "inode", p->data.file.inode);
-+            add_assoc_string(link, "type", "file", 1);
-+        } else if(p->type == APC_CACHE_ENTRY_USER) {
-+            add_assoc_string(link, "info", p->data.user.info, 1);
-+            add_assoc_long(link, "ttl", (long)p->data.user.ttl);
-+            add_assoc_string(link, "type", "user", 1);
-+        }
-+        add_assoc_long(link, "num_hits", p->num_hits);
-+        add_assoc_long(link, "mtime", p->mtime);
-+        add_assoc_long(link, "creation_time", p->creation_time);
-+        add_assoc_long(link, "deletion_time", p->deletion_time);
-+        add_assoc_long(link, "access_time", p->access_time);
-+        add_assoc_long(link, "ref_count", p->ref_count);
-+        add_assoc_long(link, "mem_size", p->mem_size);
-+        add_next_index_zval(list, link);
++    if(numbytes < 0) {
++        apc_wprint("Only %d of %d bytes written, possibly out of free disk space", numbytes, bd->size);
++        RETURN_FALSE;
 +    }
-+    add_assoc_zval(return_value, "deleted_list", list);
 +
-+    apc_cache_free_info(info);
++    RETURN_LONG(numbytes);
 +}
-+/* }}} */
 +
-+/* {{{ proto void apc_clear_cache() */
-+PHP_FUNCTION(apc_clear_cache)
-+{
-+    char *cache_type;
-+    int ct_len;
++/* {{{ proto mixed apc_bin_load(string data, [int flags])
++    Load the given binary dump into the APC file/user cache.
++ */
++PHP_FUNCTION(apc_bin_load) {
++
++    int data_len;
++    char *data;
++    long flags = 0;
++
++    if(!APCG(enabled)) {
++        apc_wprint("APC is not enabled, apc_bin_load not available.");
++        RETURN_FALSE;
++    }
 +
-+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|s", &cache_type, &ct_len) == FAILURE) {
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &data, &data_len, &flags) == FAILURE) {
 +        return;
 +    }
 +
-+    if(ZEND_NUM_ARGS()) {
-+        if(!strcasecmp(cache_type,"user")) {
-+            apc_cache_clear(apc_user_cache);
-+            RETURN_TRUE;
-+        }
++    if(!data_len || data_len != ((apc_bd_t*)data)->size -1) {
++        apc_eprint("apc_bin_load string argument does not appear to be a valid APC binary dump due to size (%d vs expected %d).", data_len, ((apc_bd_t*)data)->size -1);
++        RETURN_FALSE;
 +    }
-+    apc_cache_clear(apc_cache);
-+}
-+/* }}} */
 +
-+/* {{{ proto array apc_sma_info([bool limited]) */
-+PHP_FUNCTION(apc_sma_info)
-+{
-+    apc_sma_info_t* info;
-+    zval* block_lists;
-+    int i;
-+    zend_bool limited = 0;
++    apc_bin_load((apc_bd_t*)data, (int)flags TSRMLS_CC);
 +
-+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|b", &limited) == FAILURE) {
-+        return;
-+    }
++    RETURN_TRUE;
++}
 +
-+    info = apc_sma_info(limited);
++/* {{{ proto mixed apc_bin_loadfile(string filename, [resource context, [int flags]])
++    Load the given binary dump from the named file into the APC file/user cache.
++ */
++PHP_FUNCTION(apc_bin_loadfile) {
 +
-+    if(!info) {
-+        php_error_docref(NULL TSRMLS_CC, E_WARNING, "No APC SMA info available.  Perhaps APC is disabled via apc.enabled?");
++    char *filename;
++    int filename_len;
++    zval *zcontext = NULL;
++    long flags;
++    php_stream_context *context = NULL;
++    php_stream *stream;
++    char *data;
++    int len;
++
++    if(!APCG(enabled)) {
++        apc_wprint("APC is not enabled, apc_bin_loadfile not available.");
 +        RETURN_FALSE;
 +    }
 +
-+    array_init(return_value);
-+    add_assoc_long(return_value, "num_seg", info->num_seg);
-+    add_assoc_long(return_value, "seg_size", info->seg_size);
-+    add_assoc_long(return_value, "avail_mem", apc_sma_get_avail_mem());
-+
-+    if(limited) {
-+        apc_sma_free_info(info);
++    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|r!l", &filename, &filename_len, &zcontext, &flags) == FAILURE) {
 +        return;
 +    }
 +
-+#if ALLOC_DISTRIBUTION
-+    {
-+        size_t *adist = apc_sma_get_alloc_distribution();
-+        zval* list;
-+        ALLOC_INIT_ZVAL(list);
-+        array_init(list);
-+        for(i=0; i<30; i++) {
-+            add_next_index_long(list, adist[i]);
-+        }
-+        add_assoc_zval(return_value, "adist", list);
++    if(!filename_len) {
++        apc_eprint("apc_bin_loadfile filename argument must be a valid filename.");
++        RETURN_FALSE;
 +    }
-+#endif
-+    ALLOC_INIT_ZVAL(block_lists);
-+    array_init(block_lists);
-+
-+    for (i = 0; i < info->num_seg; i++) {
-+        apc_sma_link_t* p;
-+        zval* list;
 +
-+        ALLOC_INIT_ZVAL(list);
-+        array_init(list);
++    context = php_stream_context_from_zval(zcontext, 0);
++    stream = php_stream_open_wrapper_ex(filename, "rb",
++            ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context);
++    if (!stream) {
++        apc_eprint("Unable to read from file in apc_bin_loadfile.");
++        RETURN_FALSE;
++    }
 +
-+        for (p = info->list[i]; p != NULL; p = p->next) {
-+            zval* link;
++    len = php_stream_copy_to_mem(stream, &data, PHP_STREAM_COPY_ALL, 0);
++    if(len == 0) {
++        apc_wprint("File passed to apc_bin_loadfile was empty: %s.", filename);
++        RETURN_FALSE;
++    } else if(len < 0) {
++        apc_wprint("Error reading file passed to apc_bin_loadfile: %s.", filename);
++        RETURN_FALSE;
++    } else if(len != ((apc_bd_t*)data)->size) {
++        apc_wprint("file passed to apc_bin_loadfile does not appear to be valid due to size (%d vs expected %d).", len, ((apc_bd_t*)data)->size -1);
++        RETURN_FALSE;
++    }
++    php_stream_close(stream);
 +
-+            ALLOC_INIT_ZVAL(link);
-+            array_init(link);
++    apc_bin_load((apc_bd_t*)data, (int)flags TSRMLS_CC);
++    efree(data);
 +
-+            add_assoc_long(link, "size", p->size);
-+            add_assoc_long(link, "offset", p->offset);
-+            add_next_index_zval(list, link);
-+        }
-+        add_next_index_zval(block_lists, list);
-+    }
-+    add_assoc_zval(return_value, "block_lists", block_lists);
-+    apc_sma_free_info(info);
++    RETURN_TRUE;
 +}
 +/* }}} */
 +
-+/* {{{ _apc_store */
-+int _apc_store(char *strkey, int strkey_len, const zval *val, const unsigned int ttl, const int exclusive TSRMLS_DC) {
-+    apc_cache_entry_t *entry;
-+    apc_cache_key_t key;
-+    time_t t;
-+    size_t mem_size = 0;
-+
-+#if PHP_API_VERSION < 20041225
-+#if HAVE_APACHE && defined(APC_PHP4_STAT)
-+    t = ((request_rec *)SG(server_context))->request_time;
++/* {{{ arginfo */
++#if (PHP_MAJOR_VERSION >= 6 || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 3))
++# define PHP_APC_ARGINFO
 +#else
-+    t = time(0);
++# define PHP_APC_ARGINFO static
 +#endif
-+#else
-+    t = sapi_get_request_time(TSRMLS_C);
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_store, 0, 0, 2)
++    ZEND_ARG_INFO(0, key)
++    ZEND_ARG_INFO(0, var)
++    ZEND_ARG_INFO(0, ttl)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_clear_cache, 0, 0, 0)
++    ZEND_ARG_INFO(0, info)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_cache_info, 0, 0, 0)
++    ZEND_ARG_INFO(0, type)
++    ZEND_ARG_INFO(0, limited)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_define_constants, 0, 0, 2)
++    ZEND_ARG_INFO(0, key)
++    ZEND_ARG_INFO(0, constants)
++    ZEND_ARG_INFO(0, case_sensitive)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO(arginfo_apc_delete_file, 0)
++      ZEND_ARG_INFO(0, keys)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO(arginfo_apc_delete, 0)
++      ZEND_ARG_INFO(0, keys)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_fetch, 0, 0, 1)
++    ZEND_ARG_INFO(0, key)
++    ZEND_ARG_INFO(1, success)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_inc, 0, 0, 1)
++    ZEND_ARG_INFO(0, key)
++    ZEND_ARG_INFO(0, step)
++    ZEND_ARG_INFO(1, success)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO(arginfo_apc_cas, 0)
++    ZEND_ARG_INFO(0, key)
++    ZEND_ARG_INFO(0, old)
++    ZEND_ARG_INFO(0, new)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_load_constants, 0, 0, 1)
++    ZEND_ARG_INFO(0, key)
++    ZEND_ARG_INFO(0, case_sensitive)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_compile_file, 0, 0, 1)
++    ZEND_ARG_INFO(0, filenames)
++    ZEND_ARG_INFO(0, atomic)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_dump, 0, 0, 0)
++    ZEND_ARG_INFO(0, files)
++    ZEND_ARG_INFO(0, user_vars)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_dumpfile, 0, 0, 3)
++    ZEND_ARG_INFO(0, files)
++    ZEND_ARG_INFO(0, user_vars)
++    ZEND_ARG_INFO(0, filename)
++    ZEND_ARG_INFO(0, flags)
++    ZEND_ARG_INFO(0, context)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_load, 0, 0, 1)
++    ZEND_ARG_INFO(0, data)
++    ZEND_ARG_INFO(0, flags)
++ZEND_END_ARG_INFO()
++
++PHP_APC_ARGINFO
++ZEND_BEGIN_ARG_INFO_EX(arginfo_apc_bin_loadfile, 0, 0, 1)
++    ZEND_ARG_INFO(0, filename)
++    ZEND_ARG_INFO(0, context)
++    ZEND_ARG_INFO(0, flags)
++ZEND_END_ARG_INFO()
++/* }}} */
++
++/* {{{ apc_functions[] */
++function_entry apc_functions[] = {
++    PHP_FE(apc_cache_info,          arginfo_apc_cache_info)
++    PHP_FE(apc_clear_cache,         arginfo_apc_clear_cache)
++    PHP_FE(apc_sma_info,            arginfo_apc_clear_cache)
++    PHP_FE(apc_store,               arginfo_apc_store)
++    PHP_FE(apc_fetch,               arginfo_apc_fetch)
++    PHP_FE(apc_delete,              arginfo_apc_delete)
++    PHP_FE(apc_delete_file,         arginfo_apc_delete_file)
++    PHP_FE(apc_define_constants,    arginfo_apc_define_constants)
++    PHP_FE(apc_load_constants,      arginfo_apc_load_constants)
++    PHP_FE(apc_compile_file,        arginfo_apc_compile_file)
++    PHP_FE(apc_add,                 arginfo_apc_store)
++    PHP_FE(apc_inc,                 arginfo_apc_inc)
++    PHP_FE(apc_dec,                 arginfo_apc_inc)
++    PHP_FE(apc_cas,                 arginfo_apc_cas)
++    PHP_FE(apc_bin_dump,            arginfo_apc_bin_dump)
++    PHP_FE(apc_bin_load,            arginfo_apc_bin_load)
++    PHP_FE(apc_bin_dumpfile,        arginfo_apc_bin_dumpfile)
++    PHP_FE(apc_bin_loadfile,        arginfo_apc_bin_loadfile)
++    {NULL, NULL, NULL}
++};
++/* }}} */
++
++/* {{{ module definition structure */
++
++zend_module_entry apc_module_entry = {
++    STANDARD_MODULE_HEADER,
++    "apc",
++    apc_functions,
++    PHP_MINIT(apc),
++    PHP_MSHUTDOWN(apc),
++    PHP_RINIT(apc),
++    PHP_RSHUTDOWN(apc),
++    PHP_MINFO(apc),
++    PHP_APC_VERSION,
++    STANDARD_MODULE_PROPERTIES
++};
++
++#ifdef COMPILE_DL_APC
++ZEND_GET_MODULE(apc)
 +#endif
++/* }}} */
 +
-+    if(!APCG(enabled)) return 0;
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/php_apc.h php-5.3.1/ext/apc/php_apc.h
+--- php-5.3.1.orig/ext/apc/php_apc.h   1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/php_apc.h        1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,54 @@
++/*
++  +----------------------------------------------------------------------+
++  | APC                                                                  |
++  +----------------------------------------------------------------------+
++  | Copyright (c) 2006-2008 The PHP Group                                |
++  +----------------------------------------------------------------------+
++  | This source file is subject to version 3.01 of the PHP license,      |
++  | that is bundled with this package in the file LICENSE, and is        |
++  | available through the world-wide-web at the following url:           |
++  | http://www.php.net/license/3_01.txt                                  |
++  | If you did not receive a copy of the PHP license and are unable to   |
++  | obtain it through the world-wide-web, please send a note to          |
++  | license@php.net so we can mail you a copy immediately.               |
++  +----------------------------------------------------------------------+
++  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
++  |          George Schlossnagle <george@omniti.com>                     |
++  |          Rasmus Lerdorf <rasmus@php.net>                             |
++  +----------------------------------------------------------------------+
 +
-+    HANDLE_BLOCK_INTERRUPTIONS();
++   This software was contributed to PHP by Community Connect Inc. in 2002
++   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
++   Future revisions and derivatives of this source code must acknowledge
++   Community Connect Inc. as the original contributor of this module by
++   leaving this note intact in the source code.
 +
-+    APCG(mem_size_ptr) = &mem_size;
-+    if (!(entry = apc_cache_make_user_entry(strkey, strkey_len + 1, val, ttl))) {
-+        APCG(mem_size_ptr) = NULL;
-+        apc_cache_expunge(apc_cache,t);
-+        apc_cache_expunge(apc_user_cache,t);
-+        HANDLE_UNBLOCK_INTERRUPTIONS();
-+        return 0;
-+    }
++   All other licensing and usage conditions are those of the PHP Group.
 +
-+    if (!apc_cache_make_user_key(&key, strkey, strkey_len + 1, t)) {
-+        APCG(mem_size_ptr) = NULL;
-+        apc_cache_free_entry(entry);
-+        apc_cache_expunge(apc_cache,t);
-+        apc_cache_expunge(apc_user_cache,t);
-+        HANDLE_UNBLOCK_INTERRUPTIONS();
-+        return 0;
-+    }
++ */
 +
-+    if (!apc_cache_user_insert(apc_user_cache, key, entry, t, exclusive TSRMLS_CC)) {
-+        APCG(mem_size_ptr) = NULL;
-+        apc_cache_free_entry(entry);
-+        apc_cache_expunge(apc_cache,t);
-+        apc_cache_expunge(apc_user_cache,t);
-+        HANDLE_UNBLOCK_INTERRUPTIONS();
-+        return 0;
-+    }
++/* $Id: php_apc.h 287286 2009-08-14 10:50:22Z gopalv $ */
++
++#ifndef PHP_APC_H
++#define PHP_APC_H
++
++#include "apc_php.h"
++#include "apc_globals.h"
++
++#define PHP_APC_VERSION "3.1.3p1"
++
++extern zend_module_entry apc_module_entry;
++#define apc_module_ptr &apc_module_entry
++
++#define phpext_apc_ptr apc_module_ptr
++
++#endif /* PHP_APC_H */
++
++/*
++ * Local variables:
++ * tab-width: 4
++ * c-basic-offset: 4
++ * End:
++ * vim>600: expandtab sw=4 ts=4 sts=4 fdm=marker
++ * vim<600: expandtab sw=4 ts=4 sts=4
++ */
+diff -Naur php-5.3.1.orig/ext/apc/TECHNOTES.txt php-5.3.1/ext/apc/TECHNOTES.txt
+--- php-5.3.1.orig/ext/apc/TECHNOTES.txt       1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/TECHNOTES.txt    1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,361 @@
++APC Quick-Start Braindump
++
++This is a rapidly written braindump of how APC currently works in the
++form of a quick-start guide to start hacking on APC.
++
++1. Install and use APC a bit so you know what it does from the end-user's
++   perspective.  
++   user-space functions are all explained here: 
++
++2. Grab the current APC code from CVS:
++    
++    cvs -d:pserver:cvsread@cvs.php.net:/repository login
++    Password: phpfi
++    cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/apc
++
++   apc/php_apc.c has most of the code for the user-visible stuff.  It is
++   also a regular PHP extension in the sense that there are MINIT, MINFO, 
++   MSHUTDOWN, RSHUTDOWN, etc. functions.  
++
++3. Build it.
++
++   cd pecl/apc
++   phpize
++   ./configure --enable-apc --enable-mmap
++   make
++   cp modules/apc.so /usr/local/lib/php
++   apachectl restart
++
++4. Debugging Hints
++
++     apachectl stop
++     gdb /usr/bin/httpd
++     break ??
++     run -X
++
++   Grab the .gdbinit from the PHP source tree and have a look at the macros.
++
++5. Look through apc/apc_sma.c
++   It is a pretty standard memory allocator.
++
++   apc_sma_malloc, apc_sma_realloc, apc_sma_strdup and apc_sma_free behave to the
++   caller just like malloc, realloc, strdup and free
++
++   On server startup the MINIT hook in php_apc.c calls apc_module_init() in
++   apc_main.c which in turn calls apc_sma_init().  apc_sma_init calls into
++   apc_mmap.c to mmap the specified sized segment (I tend to just use a single
++   segment).  apc_mmap.c should be self-explanatory.  It mmaps a temp file and
++   then unlinks that file right after the mmap to provide automatic shared memory
++   cleanup in case the process dies.
++
++   Once the region has been initialized we stick a header_t at the beginning
++   of the region.  It contains the total size in header->segsize and the number 
++   of bytes available in header->avail.  
++
++   After the header comes a bit of a hack.  A zero-sized block is inserted just
++   to make things easier later on.  And then a huge block that is basically
++   the size of the entire segment minus the two (for the 0-sized block, and this one)
++   block headers.
++
++   The code for this is:
++
++     header = (header_t*) shmaddr;
++     header->segsize = sma_segsize;
++     header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) - alignword(sizeof(int));
++     memset(&header->lock,0,sizeof(header->lock));
++     sma_lock = &header->lock;
++     block = BLOCKAT(sizeof(header_t));
++     block->size = 0;
++     block->next = sizeof(header_t) + sizeof(block_t);
++     block = BLOCKAT(block->next);
++     block->size = header->avail;
++     block->next = 0;
++
++   So the shared memory looks like this:
++
++     +--------+-------+---------------------------------+
++     | header | block |             block               |
++     +--------+-------+---------------------------------+
++
++   sma_shmaddrs[0] gives you the address of header
++
++   The blocks are just a simple offset-based linked list (so no pointers):
++
++     typedef struct block_t block_t;
++     struct block_t {
++         size_t size;       /* size of this block */
++         size_t next;       /* offset in segment of next free block */
++         size_t canary;     /* canary to check for memory overwrites */
++#ifdef __APC_SMA_DEBUG__
++         int id;         /* identifier for the memory block */
++#endif
++     };
++
++   The BLOCKAT macro turns an offset into an actual address for you:
 +
-+    APCG(mem_size_ptr) = NULL;
++     #define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
 +
-+    HANDLE_UNBLOCK_INTERRUPTIONS();
++   where shmaddr = sma_shaddrs[0]
 +
-+    return 1;
-+}
-+/* }}} */
++   And the OFFSET macro goes the other way:
 +
-+/* {{{ proto int apc_store(string key, zval var [, ttl ])
-+ */
-+PHP_FUNCTION(apc_store) {
-+    zval *val;
-+    char *strkey;
-+    int strkey_len;
-+    long ttl = 0L;
++     #define OFFSET(block) ((int)(((char*)block) - (char*)shmaddr))
 +
-+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
-+        return;
-+    }
++   Allocating a block with a call to apc_sma_allocate() walks through the
++   linked list of blocks until it finds one that is >= to the requested size.
++   The first call to apc_sma_allocate() will hit the second block.  We then
++   chop up that block so it looks like this:
 +
-+    if(!strkey_len) RETURN_FALSE;
++     +--------+-------+-------+-------------------------+
++     | header | block | block |         block           |
++     +--------+-------+-------+-------------------------+
 +
-+    if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 0 TSRMLS_CC)) RETURN_TRUE;
-+    RETURN_FALSE;
-+}
-+/* }}} */
++   Then we unlink that block from the linked list so it won't show up
++   as an available block on the next allocate.  So we actually have:
 +
-+/* {{{ proto int apc_add(string key, zval var [, ttl ])
-+ */
-+PHP_FUNCTION(apc_add) {
-+    zval *val;
-+    char *strkey;
-+    int strkey_len;
-+    long ttl = 0L;
++     +--------+-------+       +-------------------------+
++     | header | block |------>|         block           |
++     +--------+-------+       +-------------------------+
 +
-+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz|l", &strkey, &strkey_len, &val, &ttl) == FAILURE) {
-+        return;
-+    }
++   And header->avail along with block->size of the remaining large
++   block are updated accordingly.  The arrow there representing the
++   link which now points to a block with an offset further along in
++   the segment.
 +
-+    if(!strkey_len) RETURN_FALSE;
++   When the block is freed using apc_sma_deallocate() the steps are
++   basically just reversed.  The block is put back and then the deallocate
++   code looks at the block before and after to see if the block immediately
++   before and after are free and if so the blocks are combined.  So you never
++   have 2 free blocks next to each other, apart from at the front with that
++   0-sized dummy block.  This mostly prevents fragmentation.  I have been
++   toying with the idea of always allocating block at 2^n boundaries to make
++   it more likely that they will be re-used to cut down on fragmentation further.
++   That's what the POWER_OF_TWO_BLOCKSIZE you see in apc_sma.c is all about.
++  
++   Of course, anytime we fiddle with our shared memory segment we lock using
++   the locking macros, LOCK() and UNLOCK().
 +
-+    if(_apc_store(strkey, strkey_len, val, (unsigned int)ttl, 1 TSRMLS_CC)) RETURN_TRUE;
-+    RETURN_FALSE;
-+}
-+/* }}} */
++   That should mostly take care of the low-level shared memory handling.
 +
-+void *apc_erealloc_wrapper(void *ptr, size_t size) {
-+    return _erealloc(ptr, size, 0 ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC);
-+}
++6. Next up is apc_main.c and apc_cache.c which implement the meat of the
++   cache logic.
 +
-+/* {{{ RETURN_ZVAL for php4 */
-+#if !defined(ZEND_ENGINE_2) && !defined(RETURN_ZVAL)
-+#define RETURN_ZVAL(zv, copy, dtor) { RETVAL_ZVAL(zv, copy, dtor); return; } 
-+#define RETVAL_ZVAL(zv, copy, dtor)     ZVAL_ZVAL(return_value, zv, copy, dtor)
-+#define ZVAL_ZVAL(z, zv, copy, dtor) {  \
-+        int is_ref, refcount;           \
-+        is_ref = (z)->is_ref;           \
-+        refcount = (z)->refcount;       \
-+        *(z) = *(zv);                   \
-+        if (copy) {                     \
-+            zval_copy_ctor(z);          \
-+        }                               \
-+        if (dtor) {                     \
-+            if (!copy) {                \
-+                ZVAL_NULL(zv);          \
-+            }                           \
-+            zval_ptr_dtor(&zv);         \
-+        }                               \
-+        (z)->is_ref = is_ref;           \
-+        (z)->refcount = refcount;       \
-+    }
-+#endif
-+/* }}} */
++   The apc_main.c file mostly calls functions in apc_sma.c to allocate memory
++   and apc_cache.c for actual cache manipulation.  
++  
++   After the shared memory segment is created and the caches are initialized,
++   apc_module_init() installs the my_compile_file() function overriding Zend's
++   version.  I'll talk about my_compile_file() and the rest of apc_compile.c
++   in the next section.  For now I will stick with apc_main.c and apc_cache.c
++   and talk about the actual caches.  A cache consists of a block of shared
++   memory returned by apc_sma_allocate() via apc_sma_malloc().  You will 
++   notice references to apc_emalloc().  apc_emalloc() is just a thin wrapper
++   around PHP's own emalloc() function which allocates per-process memory from
++   PHP's pool-based memory allocator.  Don't confuse apc_emalloc() and 
++   apc_sma_malloc() as the first is per-process and the second is shared memory.
 +
-+/* {{{ proto mixed apc_fetch(mixed key)
-+ */
-+PHP_FUNCTION(apc_fetch) {
-+    zval *key;
-+    HashTable *hash;
-+    HashPosition hpos;
-+    zval **hentry;
-+    zval *result;
-+    zval *result_entry;
-+    char *strkey;
-+    int strkey_len;
-+    apc_cache_entry_t* entry;
-+    time_t t;
++   The cache is stored in/described by this struct allocated locally using
++   emalloc():
 +
-+    if(!APCG(enabled)) RETURN_FALSE;
++     struct apc_cache_t {
++         void* shmaddr;              /* process (local) address of shared cache */
++         header_t* header;           /* cache header (stored in SHM) */
++         slot_t** slots;             /* array of cache slots (stored in SHM) */
++         int num_slots;              /* number of slots in cache */
++         int gc_ttl;                 /* maximum time on GC list for a slot */
++         int ttl;                    /* if slot is needed and entry's access time is older than this ttl, remove it */
++     };
 +
-+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &key) == FAILURE) {
-+        return;
-+    }
++   Whenever you see functions that take a 'cache' argument, this is what they
++   take.  And apc_cache_create() returns a pointer to this populated struct.
 +
-+#if PHP_API_VERSION < 20041225
-+#if HAVE_APACHE && defined(APC_PHP4_STAT)
-+    t = ((request_rec *)SG(server_context))->request_time;
-+#else 
-+    t = time(0);
-+#endif
-+#else
-+    t = sapi_get_request_time(TSRMLS_C);
-+#endif
++   At the beginning of the cache we have a header.  Remember, we are down a level now
++   from the sma stuff.  The sma stuff is the low-level shared-memory allocator which
++   has its own header which is completely separate and invisible to apc_cache.c.  
++   As far as apc_cache.c is concerned the block of memory it is working with could 
++   have come from a call to malloc().
 +
-+    if(Z_TYPE_P(key) != IS_STRING && Z_TYPE_P(key) != IS_ARRAY) {
-+        convert_to_string(key);
-+    }
-+    
-+    if(Z_TYPE_P(key) == IS_STRING) {
-+        strkey = Z_STRVAL_P(key);
-+        strkey_len = Z_STRLEN_P(key);
-+        if(!strkey_len) RETURN_FALSE;
-+        entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
-+        if(entry) {
-+            /* deep-copy returned shm zval to emalloc'ed return_value */
-+            apc_cache_fetch_zval(return_value, entry->data.user.val, apc_php_malloc, apc_php_free);
-+            apc_cache_release(apc_user_cache, entry);
-+        } else {
-+            RETURN_FALSE;
-+        }
-+    } else if(Z_TYPE_P(key) == IS_ARRAY) {
-+        hash = Z_ARRVAL_P(key);
-+        MAKE_STD_ZVAL(result);
-+        array_init(result); 
-+        zend_hash_internal_pointer_reset_ex(hash, &hpos);
-+        while(zend_hash_get_current_data_ex(hash, (void**)&hentry, &hpos) == SUCCESS) {
-+            if(Z_TYPE_PP(hentry) != IS_STRING) {
-+                apc_wprint("apc_fetch() expects a string or array of strings.");
-+                RETURN_FALSE;
-+            }
-+            entry = apc_cache_user_find(apc_user_cache, Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) + 1, t);
-+            if(entry) {
-+                /* deep-copy returned shm zval to emalloc'ed return_value */
-+                MAKE_STD_ZVAL(result_entry);
-+                apc_cache_fetch_zval(result_entry, entry->data.user.val, apc_php_malloc, apc_php_free);
-+                apc_cache_release(apc_user_cache, entry);
-+                zend_hash_add(Z_ARRVAL_P(result), Z_STRVAL_PP(hentry), Z_STRLEN_PP(hentry) +1, &result_entry, sizeof(zval*), NULL);
-+            } /* don't set values we didn't find */
-+            zend_hash_move_forward_ex(hash, &hpos);
-+        }
-+        RETURN_ZVAL(result, 0, 1);
-+    } else {
-+        apc_wprint("apc_fetch() expects a string or array of strings.");
-+        RETURN_FALSE;
-+    }
++   The header looks like this:
 +
-+    return;
-+}
-+/* }}} */
++     typedef struct header_t header_t;
++     struct header_t {
++         int num_hits;               /* total successful hits in cache */
++         int num_misses;             /* total unsuccessful hits in cache */
++         slot_t* deleted_list;       /* linked list of to-be-deleted slots */
++     };
 +
-+/* {{{ proto mixed apc_delete(string key)
-+ */
-+PHP_FUNCTION(apc_delete) {
-+    char *strkey;
-+    int strkey_len;
++   Since this is at the start of the shared memory segment, these values are accessible
++   across all the yapache processes and hence access to them has to be locked.
 +
-+    if(!APCG(enabled)) RETURN_FALSE;
++   After the header we have an array of slots.  The number of slots is user-defined
++   through the apc.num_slots ini hint.  Each slot is described by:
 +
-+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &strkey, &strkey_len) == FAILURE) {
-+        return;
-+    }
++     typedef struct slot_t slot_t;
++     struct slot_t {
++         apc_cache_key_t key;        /* slot key */
++         apc_cache_entry_t* value;   /* slot value */
++         slot_t* next;               /* next slot in linked list */
++         int num_hits;               /* number of hits to this bucket */
++       time_t creation_time;       /* time slot was initialized */
++       time_t deletion_time;       /* time slot was removed from cache */
++       time_t access_time;         /* time slot was last accessed */
++     };
 +
-+    if(!strkey_len) RETURN_FALSE;
++   The slot_t *next there is a linked list to other slots that happened to hash to the
++   same array position.
 +
-+    if(apc_cache_user_delete(apc_user_cache, strkey, strkey_len + 1)) {
-+        RETURN_TRUE;
-+    } else {
-+        RETURN_FALSE;
-+    }
-+}
-+/* }}} */
++   apc_cache_insert() shows what happens on a new cache insert.
 +
-+static void _apc_define_constants(zval *constants, zend_bool case_sensitive TSRMLS_DC) {
-+    char *const_key;
-+    unsigned int const_key_len;
-+    zval **entry;
-+    HashPosition pos;
++     slot = &cache->slots[hash(key) % cache->num_slots];
 +
-+    zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(constants), &pos);
-+    while (zend_hash_get_current_data_ex(Z_ARRVAL_P(constants), (void**)&entry, &pos) == SUCCESS) {
-+        zend_constant c;
-+        int key_type;
-+        ulong num_key;
++   cache->slots is our array of slots in the segment.  hash() is simply:
 +
-+        key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(constants), &const_key, &const_key_len, &num_key, 0, &pos);
-+        if(key_type != HASH_KEY_IS_STRING) {
-+            zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
-+            continue;
-+        }
-+        switch(Z_TYPE_PP(entry)) {
-+            case IS_LONG:
-+            case IS_DOUBLE:
-+            case IS_STRING:
-+            case IS_BOOL:
-+            case IS_RESOURCE:
-+            case IS_NULL:
-+                break;
-+            default:
-+                zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
-+                continue;
-+        }
-+        c.value = **entry;
-+        zval_copy_ctor(&c.value);
-+        c.flags = case_sensitive;
-+        c.name = zend_strndup(const_key, const_key_len);
-+        c.name_len = const_key_len;
-+#ifdef ZEND_ENGINE_2
-+        c.module_number = PHP_USER_CONSTANT;
-+#endif
-+        zend_register_constant(&c TSRMLS_CC);
++     static unsigned int hash(apc_cache_key_t key)
++     {
++         return key.data.file.device + key.data.file.inode;
++     }
 +
-+        zend_hash_move_forward_ex(Z_ARRVAL_P(constants), &pos);
-+    }
-+}
++   That is, we use the file's device and inode to uniquely identify it.  Initially
++   we had used the file's full path, but getting that requires a realpath() call which
++   is amazingly expensive since it has to stat each component of the path to resolve
++   symlinks and get rid of relative path components.  By using the device+inode we
++   can uniquely identify a file with a single stat.
 +
-+/* {{{ proto mixed apc_define_constants(string key, array constants [,bool case-sensitive])
-+ */
-+PHP_FUNCTION(apc_define_constants) {
-+    char *strkey;
-+    int strkey_len;
-+    zval *constants = NULL;
-+    zend_bool case_sensitive = 1;
-+    int argc = ZEND_NUM_ARGS();
++   So, on an insert we find the array position in the slots array by hasing the device+inode.
++   If there are currently no other slots there, we just create the slot and stick it into
++   the array:
++
++     *slot = make_slot(key, value, *slot, t)
 +
-+    if (zend_parse_parameters(argc TSRMLS_CC, "sa|b", &strkey, &strkey_len, &constants, &case_sensitive) == FAILURE) {
-+        return;
-+    }
++   If there are other slots already at this position we walk the link list to get to
++   the end.  Here is the loop:
 +
-+    if(!strkey_len) RETURN_FALSE;
++     while (*slot) {
++         if (key_equals((*slot)->key.data.file, key.data.file)) {
++           /* If existing slot for the same device+inode is different, remove it and insert the new version */
++           if ((*slot)->key.mtime != key.mtime) {
++               remove_slot(cache, slot);
++               break;
++           }
++           UNLOCK(cache);
++           return 0;
++       } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
++             remove_slot(cache, slot);
++             continue;
++         }
++         slot = &(*slot)->next;
++     }
 +
-+    _apc_define_constants(constants, case_sensitive TSRMLS_CC);
-+    if(_apc_store(strkey, strkey_len, constants, 0, 0 TSRMLS_CC)) RETURN_TRUE;
-+    RETURN_FALSE;
-+} /* }}} */
++   That first key_equals() check sees if we have an exact match meaning the file
++   is already in the cache.  Since we try to find the file in the cache before doing
++   an insert, this will generally only happen if another process managed to beat us
++   to inserting it.  If we have a newer version of the file at this point we remove
++   it an insert the new version.  If our version is not newer we just return without
++   doing anything.
 +
-+/* {{{ proto mixed apc_load_constants(string key [, bool case-sensitive])
-+ */
-+PHP_FUNCTION(apc_load_constants) {
-+    char *strkey;
-+    int strkey_len;
-+    apc_cache_entry_t* entry;
-+    time_t t;
-+    zend_bool case_sensitive = 1;
++   While walking the linked list we also check to see if the cache has a TTL defined.
++   If while walking the linked list we see a slot that has expired, we remove it
++   since we are right there looking at it.  This is the only place we remove stale
++   entries unless the shared memory segment fills up and we force a full expunge via
++   apc_cache_expunge().  apc_cache_expunge() walks the entire slots array and walks
++   down every linked list removing stale slots to free up room.  This is obviously
++   slow and thus only happens when we have run out of room.
 +
-+    if(!APCG(enabled)) RETURN_FALSE;
-+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|b", &strkey, &strkey_len, &case_sensitive) == FAILURE) {
-+        return;
-+    }
++   apc_cache_find() simply hashes and returns the entry if it is there.  If it is there
++   but older than the mtime in the entry we are looking for, we delete the one that is
++   there and return indicating we didn't find it.
 +
-+    if(!strkey_len) RETURN_FALSE;
++   Next we need to understand what an actual cache entry looks like.  Have a look at
++   apc_cache.h for the structs.  I sort of glossed over the key part earlier saying
++   that we just used the device+inode to find a hash slot.  It is actually a bit more
++   complex than that because we have two kinds of caches.  We have the standard file
++   cache containing opcode arrays, but we also have a user-controlled cache that the
++   user can insert whatever they want into via apc_store().  For the user cache we
++   obviously don't have a device+inode.  The actual identifier is provided by the user
++   as a char *.  So the key is actually a union that looks like this:
 +
-+#if PHP_API_VERSION < 20041225
-+#if HAVE_APACHE && defined(APC_PHP4_STAT)
-+    t = ((request_rec *)SG(server_context))->request_time;
-+#else 
-+    t = time(0);
-+#endif
-+#else 
-+    t = sapi_get_request_time(TSRMLS_C);
-+#endif
++     typedef union _apc_cache_key_data_t {
++         struct {
++             int device;             /* the filesystem device */
++             int inode;              /* the filesystem inode */
++         } file;
++         struct {
++             char *identifier;
++         } user;
++     } apc_cache_key_data_t;
 +
-+    entry = apc_cache_user_find(apc_user_cache, strkey, strkey_len + 1, t);
++     struct apc_cache_key_t {
++         apc_cache_key_data_t data;
++         int mtime;                  /* the mtime of this cached entry */
++     };   
 +
-+    if(entry) {
-+        _apc_define_constants(entry->data.user.val, case_sensitive TSRMLS_CC);
-+        apc_cache_release(apc_user_cache, entry);
-+        RETURN_TRUE;
-+    } else {
-+        RETURN_FALSE;
-+    }
-+}
-+/* }}} */
++   And we have two sets of functions to do inserts and finds.  apc_cache_user_find() 
++   and apc_cache_user_insert() operate on the user cache.
 +
-+/* {{{ proto boolean apc_compile_file(string filename)
-+ */
-+PHP_FUNCTION(apc_compile_file) {
-+    char *filename;
-+    int filename_len;
-+    zend_file_handle file_handle;
-+    zend_op_array *op_array;
-+    long slam_defense = 0;
-+    char** filters = NULL;
-+    zend_bool cache_by_default = 1;
-+    HashTable cg_function_table, cg_class_table, eg_function_table, eg_class_table;
-+    HashTable *cg_orig_function_table, *cg_orig_class_table, *eg_orig_function_table, *eg_orig_class_table;
++   Ok, on to the actual cache entry.  Again, because we have two kinds of caches, we
++   also have the corresponding two kinds of cache entries described by this union:
 +
-+    if(!APCG(enabled)) RETURN_FALSE;
++     typedef union _apc_cache_entry_value_t {
++         struct {
++             char *filename;             /* absolute path to source file */
++             zend_op_array* op_array;    /* op_array allocated in shared memory */
++             apc_function_t* functions;  /* array of apc_function_t's */
++             apc_class_t* classes;       /* array of apc_class_t's */
++         } file;
++         struct {
++             char *info;
++             zval *val;
++             unsigned int ttl;
++         } user;
++     } apc_cache_entry_value_t;
 +
-+    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) {
-+        return;
-+    }
++   And then the actual cache entry:
 +
-+    if(!filename) RETURN_FALSE;
++     struct apc_cache_entry_t {
++         apc_cache_entry_value_t data;
++         unsigned char type;
++         int ref_count;
++     };
 +
-+    /* reset slam defense, filters, and cache_by_default */
-+    slam_defense = APCG(slam_defense);
-+    APCG(slam_defense) = 0;
-+   
-+    filters = APCG(filters);
-+    APCG(filters) = NULL;
++   The user entry is pretty simple and not all that important for now.  I will
++   concentrate on the file entries since that is what holds the actual compiled
++   opcode arrays along with the functions and classes required by the executor.
 +
-+    cache_by_default = APCG(cache_by_default);
-+    APCG(cache_by_default) = 1;
++   apc_cache_make_file_entry() in apc_cache.c shows how an entry is constructed.
++   The main thing to understand here is that we need more than just the opcode
++   array, we also need the functions and classes created by the compiler when it
++   created the opcode array.  As far as the executor is concerned, it doesn't know
++   that it isn't operating in normal mode being called right after the parse/compile
++   phase, so we need to recreate everything so it looks exactly like it would at
++   that point. 
 +
-+    /* Replace function/class tables to avoid namespace conflicts */
-+    zend_hash_init_ex(&cg_function_table, 100, NULL, ZEND_FUNCTION_DTOR, 1, 0);
-+    cg_orig_function_table = CG(function_table);
-+    CG(function_table) = &cg_function_table;
-+    zend_hash_init_ex(&cg_class_table, 10, NULL, ZEND_CLASS_DTOR, 1, 0);
-+    cg_orig_class_table = CG(class_table);
-+    CG(class_table) = &cg_class_table;
-+    eg_orig_function_table = EG(function_table);
-+    EG(function_table) = CG(function_table);
-+    eg_orig_class_table = EG(class_table);
-+    EG(class_table) = CG(class_table);
-+    APCG(force_file_update) = 1;
-+    
-+    /* Compile the file, loading it into the cache */
-+    file_handle.type = ZEND_HANDLE_FILENAME;
-+    file_handle.filename = filename;
-+    file_handle.free_filename = 0;
-+    file_handle.opened_path = NULL;
-+    zend_try {
-+        op_array = zend_compile_file(&file_handle, ZEND_INCLUDE TSRMLS_CC);
-+    } zend_catch {
-+        apc_wprint("Error compiling %s in apc_compile_file.", filename);
-+        op_array = NULL;
-+    } zend_end_try();
++7. my_compile_file() and apc_compile.c
 +
-+    /* Return class/function tables to previous states, destroy temp tables */
-+    APCG(force_file_update) = 0;
-+    CG(function_table) = cg_orig_function_table;
-+    zend_hash_destroy(&cg_function_table);
-+    CG(class_table) = cg_orig_class_table;
-+    zend_hash_destroy(&cg_class_table);
-+    EG(function_table) = eg_orig_function_table;
-+    EG(class_table) = eg_orig_class_table;
-+    
-+    /* Restore global settings */
-+    APCG(slam_defense) = slam_defense;
-+    APCG(filters) = filters;
-+    APCG(cache_by_default) = cache_by_default;
++   my_compile_file() in apc_main.c controls where we get the opcodes from.  If
++   the user-specified filters exclude the file from being cached, then we just
++   call the original compile function and return.  Otherwise we fetch the request
++   time from Apache to avoid an extra syscall, create the key so we can look up
++   the file in the cache.  If we find it we stick it on a local stack which we
++   use at cleanup time to make sure we return everything back to normal after a 
++   request and call cached_compile() which installs the functions and classes
++   associated with the op_array in this entry and then copy the op_array down
++   into our memory space for execution.
 +
-+    if(op_array == NULL) { RETURN_FALSE; }
++   If we didn't find the file in the cache, we need to compile it and insert it.
++   To compile it we simply call the original compile function:
 +
-+    /* Free up everything */
-+    zend_destroy_file_handle(&file_handle TSRMLS_CC);
-+#ifdef ZEND_ENGINE_2
-+    destroy_op_array(op_array TSRMLS_CC);
-+#else
-+    destroy_op_array(op_array);
-+#endif
-+    efree(op_array);
++      op_array = old_compile_file(h, type TSRMLS_CC);
 +
-+    RETURN_TRUE;
-+}
-+/* }}} */
++   To do the insert we need to copy the functions, classes and the opcode array
++   the compile phase created into shared memory.  This all happens in apc_compile.c
++   in the apc_copy_op_array(), apc_copy_new_functions() and apc_copy_new_classes()
++   functions.  Then we make the file entry and do the insert.  Both of these
++   operations were described in the previous section.  
 +
-+/* {{{ apc_functions[] */
-+function_entry apc_functions[] = {
-+      PHP_FE(apc_cache_info,          NULL)
-+      PHP_FE(apc_clear_cache,         NULL)
-+      PHP_FE(apc_sma_info,            NULL)
-+      PHP_FE(apc_store,               NULL)
-+      PHP_FE(apc_fetch,               NULL)
-+      PHP_FE(apc_delete,              NULL)
-+      PHP_FE(apc_define_constants,    NULL)
-+      PHP_FE(apc_load_constants,      NULL)
-+      PHP_FE(apc_compile_file,        NULL)
-+      PHP_FE(apc_add,                 NULL)
-+      {NULL,          NULL,                           NULL}
-+};
-+/* }}} */
++8. The Optimizer
++   
++   The optimizer has been deprecated.
 +
-+/* {{{ module definition structure */
++If you made it to the end of this, you should have a pretty good idea of where things are in
++the code.  I skimmed over a lot of things, so plan on spending some time reading through the code.
 +
-+zend_module_entry apc_module_entry = {
-+      STANDARD_MODULE_HEADER,
-+      "apc",
-+      apc_functions,
-+      PHP_MINIT(apc),
-+      PHP_MSHUTDOWN(apc),
-+      PHP_RINIT(apc),
-+      PHP_RSHUTDOWN(apc),
-+      PHP_MINFO(apc),
-+      APC_VERSION,
-+      STANDARD_MODULE_PROPERTIES
-+};
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_001.phpt php-5.3.1/ext/apc/tests/apc_001.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc_001.phpt  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_001.phpt       1970-01-01 10:14:21.000000000 +0100
+@@ -0,0 +1,27 @@
++--TEST--
++APC: apc_store/fetch with strings
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
 +
-+#ifdef COMPILE_DL_APC
-+ZEND_GET_MODULE(apc)
-+#endif
-+/* }}} */
++$foo = 'hello world';
++var_dump($foo);
++apc_store('foo',$foo);
++$bar = apc_fetch('foo');
++var_dump($bar);
++$bar = 'nice';
++var_dump($bar);
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/php_apc.h php-5.2.5/ext/apc/php_apc.h
---- php-5.2.5-orig/ext/apc/php_apc.h   1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/php_apc.h        2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,52 @@
-+/*
-+  +----------------------------------------------------------------------+
-+  | APC                                                                  |
-+  +----------------------------------------------------------------------+
-+  | Copyright (c) 2006 The PHP Group                                     |
-+  +----------------------------------------------------------------------+
-+  | This source file is subject to version 3.01 of the PHP license,      |
-+  | that is bundled with this package in the file LICENSE, and is        |
-+  | available through the world-wide-web at the following url:           |
-+  | http://www.php.net/license/3_01.txt                                  |
-+  | If you did not receive a copy of the PHP license and are unable to   |
-+  | obtain it through the world-wide-web, please send a note to          |
-+  | license@php.net so we can mail you a copy immediately.               |
-+  +----------------------------------------------------------------------+
-+  | Authors: Daniel Cowgill <dcowgill@communityconnect.com>              |
-+  |          George Schlossnagle <george@omniti.com>                     |
-+  |          Rasmus Lerdorf <rasmus@php.net>                             |
-+  +----------------------------------------------------------------------+
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++string(11) "hello world"
++string(11) "hello world"
++string(4) "nice"
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_002.phpt php-5.3.1/ext/apc/tests/apc_002.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc_002.phpt  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_002.phpt       1970-01-01 10:14:21.000000000 +0100
+@@ -0,0 +1,34 @@
++--TEST--
++APC: apc_store/fetch with objects
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
 +
-+   This software was contributed to PHP by Community Connect Inc. in 2002
-+   and revised in 2005 by Yahoo! Inc. to add support for PHP 5.1.
-+   Future revisions and derivatives of this source code must acknowledge
-+   Community Connect Inc. as the original contributor of this module by
-+   leaving this note intact in the source code.
++class foo { }
++$foo = new foo;
++var_dump($foo);
++apc_store('foo',$foo);
++unset($foo);
++$bar = apc_fetch('foo');
++var_dump($bar);
++$bar->a = true;
++var_dump($bar);
 +
-+   All other licensing and usage conditions are those of the PHP Group.
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++object(foo)#%d (0) {
++}
++object(foo)#%d (0) {
++}
++object(foo)#%d (1) {
++  ["a"]=>
++  bool(true)
++}
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_003b.phpt php-5.3.1/ext/apc/tests/apc_003b.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc_003b.phpt 1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_003b.phpt      1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,117 @@
++--TEST--
++APC: apc_store/fetch with objects (php 5.3)
++--SKIPIF--
++<?php
++    require_once(dirname(__FILE__) . '/skipif.inc'); 
++    if(version_compare(zend_version(), '2.3.0') < 0) {
++              echo "skip\n";
++      }
++?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
 +
-+ */
++class foo { }
++$foo = new foo;
++var_dump($foo);
++apc_store('foo',$foo);
++unset($foo);
++$bar = apc_fetch('foo');
++var_dump($bar);
++$bar->a = true;
++var_dump($bar);
 +
-+/* $Id: php_apc.h,v 3.14 2006/03/12 00:31:45 rasmus Exp $ */
++class bar extends foo
++{
++      public    $pub = 'bar';
++      protected $pro = 'bar';
++      private   $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization
++      
++      function __construct()
++      {
++              $this->bar = true;
++      }
++      
++      function change()
++      {
++              $this->pri = 'mod';
++      }
++}
 +
-+#ifndef PHP_APC_H
-+#define PHP_APC_H
++class baz extends bar
++{
++      private $pri = 'baz';
 +
-+#include "apc_php.h"
-+#include "apc_globals.h"
++      function __construct()
++      {
++              parent::__construct();
++              $this->baz = true;
++      }
++}
 +
-+extern zend_module_entry apc_module_entry;
-+#define apc_module_ptr &apc_module_entry
++$baz = new baz;
++var_dump($baz);
++$baz->change();
++var_dump($baz);
++apc_store('baz', $baz);
++unset($baz);
++var_dump(apc_fetch('baz'));
 +
-+#define phpext_apc_ptr apc_module_ptr
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++object(foo)#%d (0) {
++}
++object(foo)#%d (0) {
++}
++object(foo)#%d (1) {
++  ["a"]=>
++  bool(true)
++}
++object(baz)#%d (6) {
++  ["pri":"baz":private]=>
++  string(3) "baz"
++  ["pub"]=>
++  string(3) "bar"
++  ["pro":protected]=>
++  string(3) "bar"
++  ["pri":"bar":private]=>
++  string(3) "bar"
++  ["bar"]=>
++  bool(true)
++  ["baz"]=>
++  bool(true)
++}
++object(baz)#%d (6) {
++  ["pri":"baz":private]=>
++  string(3) "baz"
++  ["pub"]=>
++  string(3) "bar"
++  ["pro":protected]=>
++  string(3) "bar"
++  ["pri":"bar":private]=>
++  string(3) "mod"
++  ["bar"]=>
++  bool(true)
++  ["baz"]=>
++  bool(true)
++}
++object(baz)#%d (6) {
++  ["pri":"baz":private]=>
++  string(3) "baz"
++  ["pub"]=>
++  string(3) "bar"
++  ["pro":protected]=>
++  string(3) "bar"
++  ["pri":"bar":private]=>
++  string(3) "mod"
++  ["bar"]=>
++  bool(true)
++  ["baz"]=>
++  bool(true)
++}
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_003.phpt php-5.3.1/ext/apc/tests/apc_003.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc_003.phpt  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_003.phpt       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,117 @@
++--TEST--
++APC: apc_store/fetch with objects (php pre-5.3)
++--SKIPIF--
++<?php
++    require_once(dirname(__FILE__) . '/skipif.inc'); 
++    if(version_compare(zend_version(), '2.3.0') >= 0) {
++              echo "skip\n";
++      }
++?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
 +
-+#endif /* PHP_APC_H */
++class foo { }
++$foo = new foo;
++var_dump($foo);
++apc_store('foo',$foo);
++unset($foo);
++$bar = apc_fetch('foo');
++var_dump($bar);
++$bar->a = true;
++var_dump($bar);
 +
-+/*
-+ * Local variables:
-+ * tab-width: 4
-+ * c-basic-offset: 4
-+ * End:
-+ * vim600: expandtab sw=4 ts=4 sts=4 fdm=marker
-+ * vim<600: expandtab sw=4 ts=4 sts=4
-+ */
-diff -ubrN php-5.2.5-orig/ext/apc/TECHNOTES.txt php-5.2.5/ext/apc/TECHNOTES.txt
---- php-5.2.5-orig/ext/apc/TECHNOTES.txt       1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/TECHNOTES.txt    2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,361 @@
-+APC Quick-Start Braindump
++class bar extends foo
++{
++      public    $pub = 'bar';
++      protected $pro = 'bar';
++      private   $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization
++      
++      function __construct()
++      {
++              $this->bar = true;
++      }
++      
++      function change()
++      {
++              $this->pri = 'mod';
++      }
++}
 +
-+This is a rapidly written braindump of how APC currently works in the
-+form of a quick-start guide to start hacking on APC.
++class baz extends bar
++{
++      private $pri = 'baz';
 +
-+1. Install and use APC a bit so you know what it does from the end-user's
-+   perspective.  
-+   user-space functions are all explained here: 
++      function __construct()
++      {
++              parent::__construct();
++              $this->baz = true;
++      }
++}
 +
-+2. Grab the current APC code from CVS:
-+    
-+    cvs -d:pserver:cvsread@cvs.php.net:/repository login
-+    Password: phpfi
-+    cvs -d:pserver:cvsread@cvs.php.net:/repository co pecl/apc
++$baz = new baz;
++var_dump($baz);
++$baz->change();
++var_dump($baz);
++apc_store('baz', $baz);
++unset($baz);
++var_dump(apc_fetch('baz'));
 +
-+   apc/php_apc.c has most of the code for the user-visible stuff.  It is
-+   also a regular PHP extension in the sense that there are MINIT, MINFO, 
-+   MSHUTDOWN, RSHUTDOWN, etc. functions.  
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++object(foo)#%d (0) {
++}
++object(foo)#%d (0) {
++}
++object(foo)#%d (1) {
++  ["a"]=>
++  bool(true)
++}
++object(baz)#%d (6) {
++  ["pri:private"]=>
++  string(3) "baz"
++  ["pub"]=>
++  string(3) "bar"
++  ["pro:protected"]=>
++  string(3) "bar"
++  ["pri:private"]=>
++  string(3) "bar"
++  ["bar"]=>
++  bool(true)
++  ["baz"]=>
++  bool(true)
++}
++object(baz)#%d (6) {
++  ["pri:private"]=>
++  string(3) "baz"
++  ["pub"]=>
++  string(3) "bar"
++  ["pro:protected"]=>
++  string(3) "bar"
++  ["pri:private"]=>
++  string(3) "mod"
++  ["bar"]=>
++  bool(true)
++  ["baz"]=>
++  bool(true)
++}
++object(baz)#%d (6) {
++  ["pri:private"]=>
++  string(3) "baz"
++  ["pub"]=>
++  string(3) "bar"
++  ["pro:protected"]=>
++  string(3) "bar"
++  ["pri:private"]=>
++  string(3) "mod"
++  ["bar"]=>
++  bool(true)
++  ["baz"]=>
++  bool(true)
++}
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_004.phpt php-5.3.1/ext/apc/tests/apc_004.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc_004.phpt  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_004.phpt       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,38 @@
++--TEST--
++APC: apc_store/fetch with bools 
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
 +
-+3. Build it.
++$foo = false;
++var_dump($foo);     /* false */
++apc_store('foo',$foo);
++//$success = "some string";
 +
-+   cd pecl/apc
-+   phpize
-+   ./configure --enable-apc --enable-mmap
-+   make
-+   cp modules/apc.so /usr/local/lib/php
-+   apachectl restart
++$bar = apc_fetch('foo', $success);
++var_dump($foo);     /* false */
++var_dump($bar);     /* false */
++var_dump($success); /* true  */
 +
-+4. Debugging Hints
++$bar = apc_fetch('not foo', $success);
++var_dump($foo);     /* false */
++var_dump($bar);     /* false */
++var_dump($success); /* false */
 +
-+     apachectl stop
-+     gdb /usr/bin/httpd
-+     break ??
-+     run -X
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++bool(false)
++bool(false)
++bool(false)
++bool(true)
++bool(false)
++bool(false)
++bool(false)
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_005.phpt php-5.3.1/ext/apc/tests/apc_005.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc_005.phpt  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_005.phpt       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,50 @@
++--TEST--
++APC: apc_store/fetch with arrays of objects 
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
 +
-+   Grab the .gdbinit from the PHP source tree and have a look at the macros.
++$foo = array(new stdclass(), new stdclass());
 +
-+5. Look through apc/apc_sma.c
-+   It is a pretty standard memory allocator.
++var_dump($foo);
 +
-+   apc_sma_malloc, apc_sma_realloc, apc_sma_strdup and apc_sma_free behave to the
-+   caller just like malloc, realloc, strdup and free
++apc_store('foo',$foo);
 +
-+   On server startup the MINIT hook in php_apc.c calls apc_module_init() in
-+   apc_main.c which in turn calls apc_sma_init().  apc_sma_init calls into
-+   apc_mmap.c to mmap the specified sized segment (I tend to just use a single
-+   segment).  apc_mmap.c should be self-explanatory.  It mmaps a temp file and
-+   then unlinks that file right after the mmap to provide automatic shared memory
-+   cleanup in case the process dies.
++$bar = apc_fetch('foo');
++var_dump($foo);
++var_dump($bar);
 +
-+   Once the region has been initialized we stick a header_t at the beginning
-+   of the region.  It contains the total size in header->segsize and the number 
-+   of bytes available in header->avail.  
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++array(2) {
++  [0]=>
++  object(stdClass)#1 (0) {
++  }
++  [1]=>
++  object(stdClass)#2 (0) {
++  }
++}
++array(2) {
++  [0]=>
++  object(stdClass)#1 (0) {
++  }
++  [1]=>
++  object(stdClass)#2 (0) {
++  }
++}
++array(2) {
++  [0]=>
++  object(stdClass)#3 (0) {
++  }
++  [1]=>
++  object(stdClass)#4 (0) {
++  }
++}
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_006.phpt php-5.3.1/ext/apc/tests/apc_006.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc_006.phpt  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_006.phpt       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,72 @@
++--TEST--
++APC: apc_store/fetch reference test
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++report_memleaks=0
++--FILE--
++<?php
 +
-+   After the header comes a bit of a hack.  A zero-sized block is inserted just
-+   to make things easier later on.  And then a huge block that is basically
-+   the size of the entire segment minus the two (for the 0-sized block, and this one)
-+   block headers.
++$a = 'a';
++$b = array($a);
++$c = array('c');
++$b[] = &$c;
++$b[] = &$c;
++$d = 'd';
++$b[] = &$d;
++$b[] = &$d;
++$b[] = &$d;
++$e = 'e';
++$b[] = $e;
++$b[] = $e;
++$f = array('f');
++$f[] = &$f;
++$b[] = &$f;
++apc_store('test', $b);
++$x = apc_fetch('test');
++debug_zval_dump($x);
 +
-+   The code for this is:
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++array(9) refcount(2){
++  [0]=>
++  string(1) "a" refcount(1)
++  [1]=>
++  &array(1) refcount(2){
++    [0]=>
++    string(1) "c" refcount(1)
++  }
++  [2]=>
++  &array(1) refcount(2){
++    [0]=>
++    string(1) "c" refcount(1)
++  }
++  [3]=>
++  &string(1) "d" refcount(3)
++  [4]=>
++  &string(1) "d" refcount(3)
++  [5]=>
++  &string(1) "d" refcount(3)
++  [6]=>
++  string(1) "e" refcount(2)
++  [7]=>
++  string(1) "e" refcount(2)
++  [8]=>
++  &array(2) refcount(2){
++    [0]=>
++    string(1) "f" refcount(1)
++    [1]=>
++    &array(2) refcount(2){
++      [0]=>
++      string(1) "f" refcount(1)
++      [1]=>
++      *RECURSION*
++    }
++  }
++}
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_007.phpt php-5.3.1/ext/apc/tests/apc_007.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc_007.phpt  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_007.phpt       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,46 @@
++--TEST--
++APC: apc_inc/apc_dec test
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
++apc_store('foobar',2);
++echo "\$foobar = 2 \n";
++echo "\$foobar += 1 = ".apc_inc('foobar')."\n";
++echo "\$foobar += 10 = ".apc_inc('foobar', 10)."\n";
 +
-+     header = (header_t*) shmaddr;
-+     header->segsize = sma_segsize;
-+     header->avail = sma_segsize - sizeof(header_t) - sizeof(block_t) - alignword(sizeof(int));
-+     memset(&header->lock,0,sizeof(header->lock));
-+     sma_lock = &header->lock;
-+     block = BLOCKAT(sizeof(header_t));
-+     block->size = 0;
-+     block->next = sizeof(header_t) + sizeof(block_t);
-+     block = BLOCKAT(block->next);
-+     block->size = header->avail;
-+     block->next = 0;
++echo "\$foobar -= 1 = ".apc_dec('foobar')."\n";
++echo "\$foobar -= 10 = ".apc_dec('foobar',10)."\n";
 +
-+   So the shared memory looks like this:
++echo "\$f__bar += 1 = ".(apc_inc('f__bar')?"ok":"fail")."\n";
 +
-+     +--------+-------+---------------------------------+
-+     | header | block |             block               |
-+     +--------+-------+---------------------------------+
++apc_store('perfection', "xyz");
++echo "\$perfection -= 1 = ".(apc_inc('perfection')?"ok":"epic fail")."\n";
 +
-+   sma_shmaddrs[0] gives you the address of header
++$success = false;
 +
-+   The blocks are just a simple offset-based linked list (so no pointers):
++echo "\$foobar += 1 = ".apc_inc('foobar', 1, $success)."\n";
++echo "pass by ref success ". $success . "\n";
++echo "\$foobar -= 1 = ".apc_dec('foobar', 1, $success)."\n";
++echo "pass by ref success ". $success . "\n";
 +
-+     typedef struct block_t block_t;
-+     struct block_t {
-+         size_t size;       /* size of this block */
-+         size_t next;       /* offset in segment of next free block */
-+         size_t canary;     /* canary to check for memory overwrites */
-+#ifdef __APC_SMA_DEBUG__
-+         int id;         /* identifier for the memory block */
-+#endif
-+     };
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++$foobar = 2 
++$foobar += 1 = 3
++$foobar += 10 = 13
++$foobar -= 1 = 12
++$foobar -= 10 = 2
++$f__bar += 1 = fail
++$perfection -= 1 = epic fail
++$foobar += 1 = 3
++pass by ref success 1
++$foobar -= 1 = 2
++pass by ref success 1
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_008.phpt php-5.3.1/ext/apc/tests/apc_008.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc_008.phpt  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_008.phpt       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,34 @@
++--TEST--
++APC: apc_cas test
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
++apc_store('foobar',2);
++echo "\$foobar = 2\n";
++echo "\$foobar == 1 ? 2 : 1 = ".(apc_cas('foobar', 1, 2)?"ok":"fail")."\n";
++echo "\$foobar == 2 ? 1 : 2 = ".(apc_cas('foobar', 2, 1)?"ok":"fail")."\n";
++echo "\$foobar = ".apc_fetch("foobar")."\n";
 +
-+   The BLOCKAT macro turns an offset into an actual address for you:
++echo "\$f__bar == 1 ? 2 : 1 = ".(apc_cas('f__bar', 1, 2)?"ok":"fail")."\n";
 +
-+     #define BLOCKAT(offset) ((block_t*)((char *)shmaddr + offset))
++apc_store('perfection', "xyz");
++echo "\$perfection == 2 ? 1 : 2 = ".(apc_cas('perfection', 2, 1)?"ok":"epic fail")."\n";
 +
-+   where shmaddr = sma_shaddrs[0]
++echo "\$foobar = ".apc_fetch("foobar")."\n";
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++$foobar = 2
++$foobar == 1 ? 2 : 1 = fail
++$foobar == 2 ? 1 : 2 = ok
++$foobar = 1
++$f__bar == 1 ? 2 : 1 = fail
++$perfection == 2 ? 1 : 2 = epic fail
++$foobar = 1
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_009.phpt php-5.3.1/ext/apc/tests/apc_009.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc_009.phpt  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_009.phpt       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,94 @@
++--TEST--
++APC: apc_delete_file test
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++report_memleaks=0
++--FILE--
++<?php
 +
-+   And the OFFSET macro goes the other way:
++$files = array( 'apc_009.php',
++                'apc_009-1.php',
++                'apc_009-2.php',
++                'nofile.php',
++              );
 +
-+     #define OFFSET(block) ((int)(((char*)block) - (char*)shmaddr))
++file_put_contents(dirname(__FILE__).'/apc_009-1.php', '<?php echo "test file";');
++file_put_contents(dirname(__FILE__).'/apc_009-2.php', '<?php syntaxerrorhere!');
 +
-+   Allocating a block with a call to apc_sma_allocate() walks through the
-+   linked list of blocks until it finds one that is >= to the requested size.
-+   The first call to apc_sma_allocate() will hit the second block.  We then
-+   chop up that block so it looks like this:
++apc_compile_file($files[0]);
++check_file($files[0]);
++apc_delete_file($files[0]);
++check_file($files[0]);
 +
-+     +--------+-------+-------+-------------------------+
-+     | header | block | block |         block           |
-+     +--------+-------+-------+-------------------------+
++apc_compile_file($files[0]);
++apc_delete_file(array($files[0]));
++check_file($files[0]);
 +
-+   Then we unlink that block from the linked list so it won't show up
-+   as an available block on the next allocate.  So we actually have:
++apc_compile_file($files[0]);
++$it = new APCIterator('file');
++apc_delete_file($it);
++check_file($files[0]);
 +
-+     +--------+-------+       +-------------------------+
-+     | header | block |------>|         block           |
-+     +--------+-------+       +-------------------------+
++var_dump(apc_compile_file(array($files[0], $files[1])));
++check_file(array($files[0], $files[1]));
 +
-+   And header->avail along with block->size of the remaining large
-+   block are updated accordingly.  The arrow there representing the
-+   link which now points to a block with an offset further along in
-+   the segment.
++var_dump(apc_compile_file($files));
++check_file($files);
 +
-+   When the block is freed using apc_sma_deallocate() the steps are
-+   basically just reversed.  The block is put back and then the deallocate
-+   code looks at the block before and after to see if the block immediately
-+   before and after are free and if so the blocks are combined.  So you never
-+   have 2 free blocks next to each other, apart from at the front with that
-+   0-sized dummy block.  This mostly prevents fragmentation.  I have been
-+   toying with the idea of always allocating block at 2^n boundaries to make
-+   it more likely that they will be re-used to cut down on fragmentation further.
-+   That's what the POWER_OF_TWO_BLOCKSIZE you see in apc_sma.c is all about.
-+  
-+   Of course, anytime we fiddle with our shared memory segment we lock using
-+   the locking macros, LOCK() and UNLOCK().
++function check_file($files) {
 +
-+   That should mostly take care of the low-level shared memory handling.
++  if (!is_array($files)) {
++    $files = array($files);
++  }
 +
-+6. Next up is apc_main.c and apc_cache.c which implement the meat of the
-+   cache logic.
++  $info = apc_cache_info('file');
 +
-+   The apc_main.c file mostly calls functions in apc_sma.c to allocate memory
-+   and apc_cache.c for actual cache manipulation.  
-+  
-+   After the shared memory segment is created and the caches are initialized,
-+   apc_module_init() installs the my_compile_file() function overriding Zend's
-+   version.  I'll talk about my_compile_file() and the rest of apc_compile.c
-+   in the next section.  For now I will stick with apc_main.c and apc_cache.c
-+   and talk about the actual caches.  A cache consists of a block of shared
-+   memory returned by apc_sma_allocate() via apc_sma_malloc().  You will 
-+   notice references to apc_emalloc().  apc_emalloc() is just a thin wrapper
-+   around PHP's own emalloc() function which allocates per-process memory from
-+   PHP's pool-based memory allocator.  Don't confuse apc_emalloc() and 
-+   apc_sma_malloc() as the first is per-process and the second is shared memory.
++  foreach ($files as $file) {
++    $match = 0;
++    foreach($info['cache_list'] as $cached_file) {
++      if (stristr($cached_file['filename'], $file)) $match = 1;
++    }
++    if ($match) {
++      echo "$file Found File\n";
++    } else {
++      echo "$file Not Found\n";
++    }
++  }
++}
 +
-+   The cache is stored in/described by this struct allocated locally using
-+   emalloc():
++?>
++===DONE===
++<?php exit(0); ?>
++--CLEAN--
++<?php
++unlink('apc_009-1.php');
++unlink('apc_009-2.php');
++?>
++--EXPECTF--
++apc_009.php Found File
++apc_009.php Not Found
++apc_009.php Not Found
++apc_009.php Not Found
++array(0) {
++}
++apc_009.php Found File
++apc_009-1.php Found File
++
++Parse error: syntax error, unexpected '!' in %s/apc_009-2.php on line 1
++[%s] [apc-warning] Error compiling apc_009-2.php in apc_compile_file. %s
++[%s] [apc-warning] Error compiling nofile.php in apc_compile_file. %s
++array(2) {
++  ["apc_009-2.php"]=>
++  int(-1)
++  ["nofile.php"]=>
++  int(-1)
++}
++apc_009.php Found File
++apc_009-1.php Found File
++apc_009-2.php Not Found
++nofile.php Not Found
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_010.phpt php-5.3.1/ext/apc/tests/apc_010.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc_010.phpt  1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_010.phpt       1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,83 @@
++--TEST--
++APC: apc_store/fetch/add with array of key/value pairs.
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
 +
-+     struct apc_cache_t {
-+         void* shmaddr;              /* process (local) address of shared cache */
-+         header_t* header;           /* cache header (stored in SHM) */
-+         slot_t** slots;             /* array of cache slots (stored in SHM) */
-+         int num_slots;              /* number of slots in cache */
-+         int gc_ttl;                 /* maximum time on GC list for a slot */
-+         int ttl;                    /* if slot is needed and entry's access time is older than this ttl, remove it */
-+     };
++$entries = array();
++$entries['key1'] = 'value1';
++$entries['key2'] = 'value2';
++$entries['key3'] = array('value3a','value3b');
++$entries['key4'] = 4;
 +
-+   Whenever you see functions that take a 'cache' argument, this is what they
-+   take.  And apc_cache_create() returns a pointer to this populated struct.
++var_dump(apc_store($entries));
++$cached_values = apc_fetch(array_keys($entries));
++var_dump($cached_values);
 +
-+   At the beginning of the cache we have a header.  Remember, we are down a level now
-+   from the sma stuff.  The sma stuff is the low-level shared-memory allocator which
-+   has its own header which is completely separate and invisible to apc_cache.c.  
-+   As far as apc_cache.c is concerned the block of memory it is working with could 
-+   have come from a call to malloc().
++apc_delete('key2');
++apc_delete('key4');
++$cached_values = apc_fetch(array_keys($entries));
++var_dump($cached_values);
++var_dump(apc_add($entries));
++$cached_values = apc_fetch(array_keys($entries));
++var_dump($cached_values);
 +
-+   The header looks like this:
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++array(0) {
++}
++array(4) {
++  ["key1"]=>
++  string(6) "value1"
++  ["key2"]=>
++  string(6) "value2"
++  ["key3"]=>
++  array(2) {
++    [0]=>
++    string(7) "value3a"
++    [1]=>
++    string(7) "value3b"
++  }
++  ["key4"]=>
++  int(4)
++}
++array(2) {
++  ["key1"]=>
++  string(6) "value1"
++  ["key3"]=>
++  array(2) {
++    [0]=>
++    string(7) "value3a"
++    [1]=>
++    string(7) "value3b"
++  }
++}
++array(2) {
++  ["key1"]=>
++  int(-1)
++  ["key3"]=>
++  int(-1)
++}
++array(4) {
++  ["key1"]=>
++  string(6) "value1"
++  ["key2"]=>
++  string(6) "value2"
++  ["key3"]=>
++  array(2) {
++    [0]=>
++    string(7) "value3a"
++    [1]=>
++    string(7) "value3b"
++  }
++  ["key4"]=>
++  int(4)
++}
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc53_001.phpt php-5.3.1/ext/apc/tests/apc53_001.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc53_001.phpt        1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc53_001.phpt     1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,33 @@
++--TEST--
++APC: classes with namespaces (php 5.3)
++--SKIPIF--
++<?php
++    require_once(dirname(__FILE__) . '/skipif.inc'); 
++    if(version_compare(zend_version(), '2.3.0') < 0) {
++              echo "skip\n";
++      }
++?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
 +
-+     typedef struct header_t header_t;
-+     struct header_t {
-+         int num_hits;               /* total successful hits in cache */
-+         int num_misses;             /* total unsuccessful hits in cache */
-+         slot_t* deleted_list;       /* linked list of to-be-deleted slots */
-+     };
++require_once(dirname(__FILE__) . '/php_5_3_ns.inc'); 
 +
-+   Since this is at the start of the shared memory segment, these values are accessible
-+   across all the yapache processes and hence access to them has to be locked.
++$a = new Foo\Bar\Baz();
++var_dump($a);
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++object(Foo\Bar\Baz)#1 (3) {
++  ["i"]=>
++  int(1)
++  ["f":protected]=>
++  float(3.14)
++  ["s":"Foo\Bar\Baz":private]=>
++  string(11) "hello world"
++}
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc53_002.phpt php-5.3.1/ext/apc/tests/apc53_002.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc53_002.phpt        1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc53_002.phpt     1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,47 @@
++--TEST--
++APC: global spaces (php 5.3)
++--SKIPIF--
++<?php
++    require_once(dirname(__FILE__) . '/skipif.inc'); 
++    if(version_compare(zend_version(), '2.3.0') < 0) {
++              echo "skip\n";
++      }
++?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
 +
-+   After the header we have an array of slots.  The number of slots is user-defined
-+   through the apc.num_slots ini hint.  Each slot is described by:
++require_once(dirname(__FILE__) . '/php_5_3_ns.inc'); 
 +
-+     typedef struct slot_t slot_t;
-+     struct slot_t {
-+         apc_cache_key_t key;        /* slot key */
-+         apc_cache_entry_t* value;   /* slot value */
-+         slot_t* next;               /* next slot in linked list */
-+         int num_hits;               /* number of hits to this bucket */
-+       time_t creation_time;       /* time slot was initialized */
-+       time_t deletion_time;       /* time slot was removed from cache */
-+       time_t access_time;         /* time slot was last accessed */
-+     };
++$a = new Foo\Bar\Baz();
++$a->foo();
++var_dump(Foo\Bar\sort());
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++array(4) {
++  [0]=>
++  int(1)
++  [1]=>
++  int(2)
++  [2]=>
++  int(3)
++  [3]=>
++  int(4)
++}
++array(4) {
++  [0]=>
++  int(1)
++  [1]=>
++  int(2)
++  [2]=>
++  int(3)
++  [3]=>
++  int(4)
++}
++string(8) "IT WORKS"
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc53_003.phpt php-5.3.1/ext/apc/tests/apc53_003.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc53_003.phpt        1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc53_003.phpt     1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,31 @@
++--TEST--
++APC: anonymous functions (php 5.3)
++--SKIPIF--
++<?php
++    require_once(dirname(__FILE__) . '/skipif.inc'); 
++    if(version_compare(zend_version(), '2.3.0') < 0) {
++              echo "skip\n";
++      }
++?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
 +
-+   The slot_t *next there is a linked list to other slots that happened to hash to the
-+   same array position.
++$greet = function($name)
++{
++    printf("Hello %s\r\n", $name);
++};
 +
-+   apc_cache_insert() shows what happens on a new cache insert.
++$greet('World');
++$greet('PHP');
 +
-+     slot = &cache->slots[hash(key) % cache->num_slots];
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++Hello World
++Hello PHP
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc53_004.phpt php-5.3.1/ext/apc/tests/apc53_004.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc53_004.phpt        1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc53_004.phpt     1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,33 @@
++--TEST--
++APC: closures (php 5.3)
++--SKIPIF--
++<?php
++    require_once(dirname(__FILE__) . '/skipif.inc'); 
++    if(version_compare(zend_version(), '2.3.0') < 0) {
++              echo "skip\n";
++      }
++?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
++function multiplier($n) {
++      return function($i) use ($n) {
++              return $n * $i;
++      };
++}
 +
-+   cache->slots is our array of slots in the segment.  hash() is simply:
++$doubler = multiplier(2);
++$tripler = multiplier(3);
 +
-+     static unsigned int hash(apc_cache_key_t key)
-+     {
-+         return key.data.file.device + key.data.file.inode;
-+     }
++echo "double of 9 is ".$doubler(9)."\n";
++echo "triple of 4 is ".$tripler(4)."\n";
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++double of 9 is 18
++triple of 4 is 12
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc53_005.phpt php-5.3.1/ext/apc/tests/apc53_005.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc53_005.phpt        1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc53_005.phpt     1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,35 @@
++--TEST--
++APC: goto (php 5.3)
++--SKIPIF--
++<?php
++    require_once(dirname(__FILE__) . '/skipif.inc'); 
++    if(version_compare(zend_version(), '2.3.0') < 0) {
++              echo "skip\n";
++      }
++?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
 +
-+   That is, we use the file's device and inode to uniquely identify it.  Initially
-+   we had used the file's full path, but getting that requires a realpath() call which
-+   is amazingly expensive since it has to stat each component of the path to resolve
-+   symlinks and get rid of relative path components.  By using the device+inode we
-+   can uniquely identify a file with a single stat.
++$i = 0;
++a: 
++$i++;
++if($i % 3 == 0) goto b;
++echo "$i\n";
++b:
++if($i < 10) goto a;
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++1
++2
++4
++5
++7
++8
++10
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_bin_001.phpt php-5.3.1/ext/apc/tests/apc_bin_001.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc_bin_001.phpt      1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_bin_001.phpt   1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,23 @@
++--TEST--
++APC: bindump user cache
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++--FILE--
++<?php
++apc_clear_cache('file');
++apc_store('testkey','testvalue');
++$dump = apc_bin_dump(array(), NULL);
++apc_clear_cache('user');
++var_dump(apc_fetch('testkey'));
++apc_bin_load($dump, APC_BIN_VERIFY_MD5 | APC_BIN_VERIFY_CRC32);
++var_dump(apc_fetch('testkey'));
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECTF--
++bool(false)
++string(9) "testvalue"
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_bin_002-1.inc php-5.3.1/ext/apc/tests/apc_bin_002-1.inc
+--- php-5.3.1.orig/ext/apc/tests/apc_bin_002-1.inc     1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_bin_002-1.inc  1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,42 @@
++<?php
 +
-+   So, on an insert we find the array position in the slots array by hasing the device+inode.
-+   If there are currently no other slots there, we just create the slot and stick it into
-+   the array:
++$my_class = New my_class();
++$my_i_class = New my_i_class();
 +
-+     *slot = make_slot(key, value, *slot, t)
++echo "apc bindump 002 test\n";
++echo "\n";
++echo "global scope execution:            Success\n";
++echo "\n";
++echo "function execution:                ".my_function()."\n";
++echo "\n";
 +
-+   If there are other slots already at this position we walk the link list to get to
-+   the end.  Here is the loop:
++echo "class static method:               ".my_class::my_static_method()."\n";
++echo "class dynamic method:              ".$my_class->my_method()."\n";
++echo "class static property:             ".my_class::$my_static_property."\n";
++echo "class dynamic property:            ".$my_class->my_property."\n";
++echo "class constant:                    ".my_class::my_constant."\n";
++echo "\n";
++echo "inherited class static method:     ".my_i_class::my_static_method()."\n";
++echo "inherited class dynamic method:    ".$my_i_class->my_method()."\n";
++echo "inherited class static property:   ".my_i_class::$my_static_property."\n";
++echo "inherited class dynamic property:  ".$my_i_class->my_property."\n";
++echo "inherited class constant:          ".my_i_class::my_constant."\n";
++echo "\n";
 +
-+     while (*slot) {
-+         if (key_equals((*slot)->key.data.file, key.data.file)) {
-+           /* If existing slot for the same device+inode is different, remove it and insert the new version */
-+           if ((*slot)->key.mtime != key.mtime) {
-+               remove_slot(cache, slot);
-+               break;
-+           }
-+           UNLOCK(cache);
-+           return 0;
-+       } else if(cache->ttl && (*slot)->access_time < (t - cache->ttl)) {
-+             remove_slot(cache, slot);
-+             continue;
-+         }
-+         slot = &(*slot)->next;
-+     }
 +
-+   That first key_equals() check sees if we have an exact match meaning the file
-+   is already in the cache.  Since we try to find the file in the cache before doing
-+   an insert, this will generally only happen if another process managed to beat us
-+   to inserting it.  If we have a newer version of the file at this point we remove
-+   it an insert the new version.  If our version is not newer we just return without
-+   doing anything.
 +
-+   While walking the linked list we also check to see if the cache has a TTL defined.
-+   If while walking the linked list we see a slot that has expired, we remove it
-+   since we are right there looking at it.  This is the only place we remove stale
-+   entries unless the shared memory segment fills up and we force a full expunge via
-+   apc_cache_expunge().  apc_cache_expunge() walks the entire slots array and walks
-+   down every linked list removing stale slots to free up room.  This is obviously
-+   slow and thus only happens when we have run out of room.
++function my_function() { return "Success"; }
 +
-+   apc_cache_find() simply hashes and returns the entry if it is there.  If it is there
-+   but older than the mtime in the entry we are looking for, we delete the one that is
-+   there and return indicating we didn't find it.
 +
-+   Next we need to understand what an actual cache entry looks like.  Have a look at
-+   apc_cache.h for the structs.  I sort of glossed over the key part earlier saying
-+   that we just used the device+inode to find a hash slot.  It is actually a bit more
-+   complex than that because we have two kinds of caches.  We have the standard file
-+   cache containing opcode arrays, but we also have a user-controlled cache that the
-+   user can insert whatever they want into via apc_store().  For the user cache we
-+   obviously don't have a device+inode.  The actual identifier is provided by the user
-+   as a char *.  So the key is actually a union that looks like this:
++class my_class {
++  static $my_static_property = "Success";
++  var $my_property = "Success";
++  const my_constant = "Success";
++  static function my_static_method() { return "Success"; }
++  function my_method() { return "Success"; }
++}
 +
-+     typedef union _apc_cache_key_data_t {
-+         struct {
-+             int device;             /* the filesystem device */
-+             int inode;              /* the filesystem inode */
-+         } file;
-+         struct {
-+             char *identifier;
-+         } user;
-+     } apc_cache_key_data_t;
++class my_i_class extends my_class {
++  function dummy() { return 1; }
++}
 +
-+     struct apc_cache_key_t {
-+         apc_cache_key_data_t data;
-+         int mtime;                  /* the mtime of this cached entry */
-+     };   
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_bin_002-2.inc php-5.3.1/ext/apc/tests/apc_bin_002-2.inc
+--- php-5.3.1.orig/ext/apc/tests/apc_bin_002-2.inc     1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_bin_002-2.inc  1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,5 @@
++<?php
 +
-+   And we have two sets of functions to do inserts and finds.  apc_cache_user_find() 
-+   and apc_cache_user_insert() operate on the user cache.
++echo "Failed to use cached version!\n";
 +
-+   Ok, on to the actual cache entry.  Again, because we have two kinds of caches, we
-+   also have the corresponding two kinds of cache entries described by this union:
++?>
+diff -Naur php-5.3.1.orig/ext/apc/tests/apc_bin_002.phpt php-5.3.1/ext/apc/tests/apc_bin_002.phpt
+--- php-5.3.1.orig/ext/apc/tests/apc_bin_002.phpt      1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/apc_bin_002.phpt   1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,53 @@
++--TEST--
++APC: bindump file cache part 1
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.stat=0
++apc.cache_by_default=1
++apc.filters=
++report_memleaks = Off
++--FILE--
++<?php
 +
-+     typedef union _apc_cache_entry_value_t {
-+         struct {
-+             char *filename;             /* absolute path to source file */
-+             zend_op_array* op_array;    /* op_array allocated in shared memory */
-+             apc_function_t* functions;  /* array of apc_function_t's */
-+             apc_class_t* classes;       /* array of apc_class_t's */
-+         } file;
-+         struct {
-+             char *info;
-+             zval *val;
-+             unsigned int ttl;
-+         } user;
-+     } apc_cache_entry_value_t;
++define('filename',dirname(__FILE__).'/apc_bin_002.inc');
++define('filename1',dirname(__FILE__).'/apc_bin_002-1.inc');
++define('filename2',dirname(__FILE__).'/apc_bin_002-2.inc');
 +
-+   And then the actual cache entry:
++copy(filename1, filename);
++apc_compile_file(filename);
++$data = apc_bin_dump(NULL, NULL);
 +
-+     struct apc_cache_entry_t {
-+         apc_cache_entry_value_t data;
-+         unsigned char type;
-+         int ref_count;
-+     };
++apc_clear_cache();
 +
-+   The user entry is pretty simple and not all that important for now.  I will
-+   concentrate on the file entries since that is what holds the actual compiled
-+   opcode arrays along with the functions and classes required by the executor.
++copy(filename2, filename);
++apc_bin_load($data, APC_BIN_VERIFY_MD5 | APC_BIN_VERIFY_CRC32);
++include(filename);
 +
-+   apc_cache_make_file_entry() in apc_cache.c shows how an entry is constructed.
-+   The main thing to understand here is that we need more than just the opcode
-+   array, we also need the functions and classes created by the compiler when it
-+   created the opcode array.  As far as the executor is concerned, it doesn't know
-+   that it isn't operating in normal mode being called right after the parse/compile
-+   phase, so we need to recreate everything so it looks exactly like it would at
-+   that point. 
++unlink(filename);
 +
-+7. my_compile_file() and apc_compile.c
++?>
++===DONE===
++<?  php exit(0); ?>
++--EXPECTF--
++apc bindump 002 test
 +
-+   my_compile_file() in apc_main.c controls where we get the opcodes from.  If
-+   the user-specified filters exclude the file from being cached, then we just
-+   call the original compile function and return.  Otherwise we fetch the request
-+   time from Apache to avoid an extra syscall, create the key so we can look up
-+   the file in the cache.  If we find it we stick it on a local stack which we
-+   use at cleanup time to make sure we return everything back to normal after a 
-+   request and call cached_compile() which installs the functions and classes
-+   associated with the op_array in this entry and then copy the op_array down
-+   into our memory space for execution.
++global scope execution:            Success
 +
-+   If we didn't find the file in the cache, we need to compile it and insert it.
-+   To compile it we simply call the original compile function:
++function execution:                Success
 +
-+      op_array = old_compile_file(h, type TSRMLS_CC);
++class static method:               Success
++class dynamic method:              Success
++class static property:             Success
++class dynamic property:            Success
++class constant:                    Success
 +
-+   To do the insert we need to copy the functions, classes and the opcode array
-+   the compile phase created into shared memory.  This all happens in apc_compile.c
-+   in the apc_copy_op_array(), apc_copy_new_functions() and apc_copy_new_classes()
-+   functions.  Then we make the file entry and do the insert.  Both of these
-+   operations were described in the previous section.  
++inherited class static method:     Success
++inherited class dynamic method:    Success
++inherited class static property:   Success
++inherited class dynamic property:  Success
++inherited class constant:          Success
 +
-+8. The Optimizer
-+   
-+   The optimizer has been deprecated.
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/iterator_001.phpt php-5.3.1/ext/apc/tests/iterator_001.phpt
+--- php-5.3.1.orig/ext/apc/tests/iterator_001.phpt     1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/iterator_001.phpt  1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,110 @@
++--TEST--
++APC: APCIterator general
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
 +
-+If you made it to the end of this, you should have a pretty good idea of where things are in
-+the code.  I skimmed over a lot of things, so plan on spending some time reading through the code.
++$it = new APCIterator('user');
++for($i = 0; $i < 41; $i++) {
++  apc_store("key$i", "value$i");
++}
++foreach($it as $key=>$value) {
++  $vals[$key] = $value['key'];
++}
++ksort($vals);
++var_dump($vals);
 +
-diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_001.phpt php-5.2.5/ext/apc/tests/apc_001.phpt
---- php-5.2.5-orig/ext/apc/tests/apc_001.phpt  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/tests/apc_001.phpt       2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,27 @@
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECT--
++array(41) {
++  ["key0"]=>
++  string(4) "key0"
++  ["key1"]=>
++  string(4) "key1"
++  ["key10"]=>
++  string(5) "key10"
++  ["key11"]=>
++  string(5) "key11"
++  ["key12"]=>
++  string(5) "key12"
++  ["key13"]=>
++  string(5) "key13"
++  ["key14"]=>
++  string(5) "key14"
++  ["key15"]=>
++  string(5) "key15"
++  ["key16"]=>
++  string(5) "key16"
++  ["key17"]=>
++  string(5) "key17"
++  ["key18"]=>
++  string(5) "key18"
++  ["key19"]=>
++  string(5) "key19"
++  ["key2"]=>
++  string(4) "key2"
++  ["key20"]=>
++  string(5) "key20"
++  ["key21"]=>
++  string(5) "key21"
++  ["key22"]=>
++  string(5) "key22"
++  ["key23"]=>
++  string(5) "key23"
++  ["key24"]=>
++  string(5) "key24"
++  ["key25"]=>
++  string(5) "key25"
++  ["key26"]=>
++  string(5) "key26"
++  ["key27"]=>
++  string(5) "key27"
++  ["key28"]=>
++  string(5) "key28"
++  ["key29"]=>
++  string(5) "key29"
++  ["key3"]=>
++  string(4) "key3"
++  ["key30"]=>
++  string(5) "key30"
++  ["key31"]=>
++  string(5) "key31"
++  ["key32"]=>
++  string(5) "key32"
++  ["key33"]=>
++  string(5) "key33"
++  ["key34"]=>
++  string(5) "key34"
++  ["key35"]=>
++  string(5) "key35"
++  ["key36"]=>
++  string(5) "key36"
++  ["key37"]=>
++  string(5) "key37"
++  ["key38"]=>
++  string(5) "key38"
++  ["key39"]=>
++  string(5) "key39"
++  ["key4"]=>
++  string(4) "key4"
++  ["key40"]=>
++  string(5) "key40"
++  ["key5"]=>
++  string(4) "key5"
++  ["key6"]=>
++  string(4) "key6"
++  ["key7"]=>
++  string(4) "key7"
++  ["key8"]=>
++  string(4) "key8"
++  ["key9"]=>
++  string(4) "key9"
++}
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/iterator_002.phpt php-5.3.1/ext/apc/tests/iterator_002.phpt
+--- php-5.3.1.orig/ext/apc/tests/iterator_002.phpt     1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/iterator_002.phpt  1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,36 @@
 +--TEST--
-+APC: apc_store/fetch with strings
++APC: APCIterator regex
 +--SKIPIF--
 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
 +--INI--
@@ -15284,28 +19326,37 @@ diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_001.phpt php-5.2.5/ext/apc/tests/apc
 +--FILE--
 +<?php
 +
-+$foo = 'hello world';
-+var_dump($foo);
-+apc_store('foo',$foo);
-+$bar = apc_fetch('foo');
-+var_dump($bar);
-+$bar = 'nice';
-+var_dump($bar);
++$it = new APCIterator('user', '/key[0-9]0/');
++for($i = 0; $i < 41; $i++) {
++  apc_store("key$i", "value$i");
++}
++foreach($it as $key=>$value) {
++  $vals[$key] = $value['key'];
++}
++ksort($vals);
++var_dump($vals);
 +
 +?>
 +===DONE===
 +<?php exit(0); ?>
-+--EXPECTF--
-+string(11) "hello world"
-+string(11) "hello world"
-+string(4) "nice"
++--EXPECT--
++array(4) {
++  ["key10"]=>
++  string(5) "key10"
++  ["key20"]=>
++  string(5) "key20"
++  ["key30"]=>
++  string(5) "key30"
++  ["key40"]=>
++  string(5) "key40"
++}
 +===DONE===
-diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_002.phpt php-5.2.5/ext/apc/tests/apc_002.phpt
---- php-5.2.5-orig/ext/apc/tests/apc_002.phpt  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/tests/apc_002.phpt       2007-12-26 16:51:32.000000000 -0600
-@@ -0,0 +1,34 @@
+diff -Naur php-5.3.1.orig/ext/apc/tests/iterator_003.phpt php-5.3.1/ext/apc/tests/iterator_003.phpt
+--- php-5.3.1.orig/ext/apc/tests/iterator_003.phpt     1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/iterator_003.phpt  1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,110 @@
 +--TEST--
-+APC: apc_store/fetch with objects
++APC: APCIterator chunk size
 +--SKIPIF--
 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
 +--INI--
@@ -15315,35 +19366,151 @@ diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_002.phpt php-5.2.5/ext/apc/tests/apc
 +--FILE--
 +<?php
 +
-+class foo { }
-+$foo = new foo;
-+var_dump($foo);
-+apc_store('foo',$foo);
-+unset($foo);
-+$bar = apc_fetch('foo');
-+var_dump($bar);
-+$bar->a = true;
-+var_dump($bar);
++$it = new APCIterator('user', NULL, APC_ITER_ALL, 10);
++for($i = 0; $i < 41; $i++) {
++  apc_store("key$i", "value$i");
++}
++foreach($it as $key=>$value) {
++  $vals[$key] = $value['key'];
++}
++ksort($vals);
++var_dump($vals);
 +
 +?>
 +===DONE===
 +<?php exit(0); ?>
-+--EXPECTF--
-+object(foo)#%d (0) {
++--EXPECT--
++array(41) {
++  ["key0"]=>
++  string(4) "key0"
++  ["key1"]=>
++  string(4) "key1"
++  ["key10"]=>
++  string(5) "key10"
++  ["key11"]=>
++  string(5) "key11"
++  ["key12"]=>
++  string(5) "key12"
++  ["key13"]=>
++  string(5) "key13"
++  ["key14"]=>
++  string(5) "key14"
++  ["key15"]=>
++  string(5) "key15"
++  ["key16"]=>
++  string(5) "key16"
++  ["key17"]=>
++  string(5) "key17"
++  ["key18"]=>
++  string(5) "key18"
++  ["key19"]=>
++  string(5) "key19"
++  ["key2"]=>
++  string(4) "key2"
++  ["key20"]=>
++  string(5) "key20"
++  ["key21"]=>
++  string(5) "key21"
++  ["key22"]=>
++  string(5) "key22"
++  ["key23"]=>
++  string(5) "key23"
++  ["key24"]=>
++  string(5) "key24"
++  ["key25"]=>
++  string(5) "key25"
++  ["key26"]=>
++  string(5) "key26"
++  ["key27"]=>
++  string(5) "key27"
++  ["key28"]=>
++  string(5) "key28"
++  ["key29"]=>
++  string(5) "key29"
++  ["key3"]=>
++  string(4) "key3"
++  ["key30"]=>
++  string(5) "key30"
++  ["key31"]=>
++  string(5) "key31"
++  ["key32"]=>
++  string(5) "key32"
++  ["key33"]=>
++  string(5) "key33"
++  ["key34"]=>
++  string(5) "key34"
++  ["key35"]=>
++  string(5) "key35"
++  ["key36"]=>
++  string(5) "key36"
++  ["key37"]=>
++  string(5) "key37"
++  ["key38"]=>
++  string(5) "key38"
++  ["key39"]=>
++  string(5) "key39"
++  ["key4"]=>
++  string(4) "key4"
++  ["key40"]=>
++  string(5) "key40"
++  ["key5"]=>
++  string(4) "key5"
++  ["key6"]=>
++  string(4) "key6"
++  ["key7"]=>
++  string(4) "key7"
++  ["key8"]=>
++  string(4) "key8"
++  ["key9"]=>
++  string(4) "key9"
 +}
-+object(foo)#%d (0) {
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/iterator_004.phpt php-5.3.1/ext/apc/tests/iterator_004.phpt
+--- php-5.3.1.orig/ext/apc/tests/iterator_004.phpt     1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/iterator_004.phpt  1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,36 @@
++--TEST--
++APC: APCIterator regex & chunk size & list
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
++
++$it = new APCIterator('user', '/key[0-9]0/', APC_ITER_ALL, 1, APC_LIST_ACTIVE);
++for($i = 0; $i < 41; $i++) {
++  apc_store("key$i", "value$i");
 +}
-+object(foo)#%d (1) {
-+  ["a"]=>
-+  bool(true)
++foreach($it as $key=>$value) {
++  $vals[$key] = $value['key'];
++}
++ksort($vals);
++var_dump($vals);
++
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECT--
++array(4) {
++  ["key10"]=>
++  string(5) "key10"
++  ["key20"]=>
++  string(5) "key20"
++  ["key30"]=>
++  string(5) "key30"
++  ["key40"]=>
++  string(5) "key40"
 +}
 +===DONE===
-diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_003.phpt php-5.2.5/ext/apc/tests/apc_003.phpt
---- php-5.2.5-orig/ext/apc/tests/apc_003.phpt  1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/tests/apc_003.phpt       2007-12-26 16:51:32.000000000 -0600
+diff -Naur php-5.3.1.orig/ext/apc/tests/iterator_005.phpt php-5.3.1/ext/apc/tests/iterator_005.phpt
+--- php-5.3.1.orig/ext/apc/tests/iterator_005.phpt     1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/iterator_005.phpt  1970-01-01 10:13:08.000000000 +0100
 @@ -0,0 +1,112 @@
 +--TEST--
-+APC: apc_store/fetch with objects
++APC: APCIterator delete
 +--SKIPIF--
 +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
 +--INI--
@@ -15353,110 +19520,1711 @@ diff -ubrN php-5.2.5-orig/ext/apc/tests/apc_003.phpt php-5.2.5/ext/apc/tests/apc
 +--FILE--
 +<?php
 +
-+class foo { }
-+$foo = new foo;
-+var_dump($foo);
-+apc_store('foo',$foo);
-+unset($foo);
-+$bar = apc_fetch('foo');
-+var_dump($bar);
-+$bar->a = true;
-+var_dump($bar);
++$vals = array();
++$vals2 = array();
++$it = new APCIterator('user', '/key[0-9]0/');
++for($i = 0; $i < 41; $i++) {
++  apc_store("key$i", "value$i");
++}
++apc_delete($it);
++$it2 = new APCIterator('user');
++foreach($it as $key=>$value) {
++  $vals[$key] = $value['key'];
++}
++foreach($it2 as $key=>$value) {
++  $vals2[$key] = $value['key'];
++}
++ksort($vals2);
++var_dump($vals);
++var_dump($vals2);
 +
-+class bar extends foo
-+{
-+      public    $pub = 'bar';
-+      protected $pro = 'bar';
-+      private   $pri = 'bar'; // we don't see this, we'd need php 5.1 new serialization
-+      
-+      function __construct()
-+      {
-+              $this->bar = true;
-+      }
-+      
-+      function change()
-+      {
-+              $this->pri = 'mod';
-+      }
++?>
++===DONE===
++<?php exit(0); ?>
++--EXPECT--
++array(0) {
++}
++array(37) {
++  ["key0"]=>
++  string(4) "key0"
++  ["key1"]=>
++  string(4) "key1"
++  ["key11"]=>
++  string(5) "key11"
++  ["key12"]=>
++  string(5) "key12"
++  ["key13"]=>
++  string(5) "key13"
++  ["key14"]=>
++  string(5) "key14"
++  ["key15"]=>
++  string(5) "key15"
++  ["key16"]=>
++  string(5) "key16"
++  ["key17"]=>
++  string(5) "key17"
++  ["key18"]=>
++  string(5) "key18"
++  ["key19"]=>
++  string(5) "key19"
++  ["key2"]=>
++  string(4) "key2"
++  ["key21"]=>
++  string(5) "key21"
++  ["key22"]=>
++  string(5) "key22"
++  ["key23"]=>
++  string(5) "key23"
++  ["key24"]=>
++  string(5) "key24"
++  ["key25"]=>
++  string(5) "key25"
++  ["key26"]=>
++  string(5) "key26"
++  ["key27"]=>
++  string(5) "key27"
++  ["key28"]=>
++  string(5) "key28"
++  ["key29"]=>
++  string(5) "key29"
++  ["key3"]=>
++  string(4) "key3"
++  ["key31"]=>
++  string(5) "key31"
++  ["key32"]=>
++  string(5) "key32"
++  ["key33"]=>
++  string(5) "key33"
++  ["key34"]=>
++  string(5) "key34"
++  ["key35"]=>
++  string(5) "key35"
++  ["key36"]=>
++  string(5) "key36"
++  ["key37"]=>
++  string(5) "key37"
++  ["key38"]=>
++  string(5) "key38"
++  ["key39"]=>
++  string(5) "key39"
++  ["key4"]=>
++  string(4) "key4"
++  ["key5"]=>
++  string(4) "key5"
++  ["key6"]=>
++  string(4) "key6"
++  ["key7"]=>
++  string(4) "key7"
++  ["key8"]=>
++  string(4) "key8"
++  ["key9"]=>
++  string(4) "key9"
 +}
++===DONE===
+diff -Naur php-5.3.1.orig/ext/apc/tests/iterator_006.phpt php-5.3.1/ext/apc/tests/iterator_006.phpt
+--- php-5.3.1.orig/ext/apc/tests/iterator_006.phpt     1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/iterator_006.phpt  1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,1535 @@
++--TEST--
++APC: APCIterator formats 
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++apc.file_update_protection=0
++--FILE--
++<?php
 +
-+class baz extends bar
-+{
-+      private $pri = 'baz';
++$formats = array( 
++                  APC_ITER_TYPE,
++                  APC_ITER_KEY,
++                  APC_ITER_FILENAME,
++                  APC_ITER_DEVICE,
++                  APC_ITER_INODE,
++                  APC_ITER_VALUE,
++                  APC_ITER_MD5,
++                  APC_ITER_NUM_HITS,
++                  APC_ITER_MTIME,
++                  APC_ITER_CTIME,
++                  APC_ITER_DTIME,
++                  APC_ITER_ATIME,
++                  APC_ITER_REFCOUNT,
++                  APC_ITER_MEM_SIZE,
++                  APC_ITER_TTL,
++                  APC_ITER_NONE,
++                  APC_ITER_ALL,
++                  APC_ITER_ALL & ~APC_ITER_TTL,
++                  APC_ITER_KEY | APC_ITER_NUM_HITS | APC_ITER_MEM_SIZE,
++                );
 +
-+      function __construct()
-+      {
-+              parent::__construct();
-+              $this->baz = true;
-+      }
++$it_array = array();
++
++foreach ($formats as $idx => $format) {
++  $it_array[$idx] = new APCIterator('user', NULL, $format);
 +}
 +
-+$baz = new baz;
-+var_dump($baz);
-+$baz->change();
-+var_dump($baz);
-+apc_store('baz', $baz);
-+unset($baz);
-+var_dump(apc_fetch('baz'));
++for($i = 0; $i < 11; $i++) {
++  apc_store("key$i", "value$i");
++}
++
++foreach ($it_array as $idx => $it) {
++  print_it($it, $idx);
++}
++
++function print_it($it, $idx) {
++  echo "IT #$idx\n";
++  echo "============================\n";
++  foreach ($it as $key=>$value) {
++    var_dump($key);
++    var_dump($value);
++  }
++  echo "============================\n\n";
++}
 +
 +?>
 +===DONE===
 +<?php exit(0); ?>
 +--EXPECTF--
-+object(foo)#%d (0) {
++IT #0
++============================
++string(4) "key0"
++array(1) {
++  ["type"]=>
++  string(4) "user"
++}
++string(4) "key1"
++array(1) {
++  ["type"]=>
++  string(4) "user"
++}
++string(4) "key2"
++array(1) {
++  ["type"]=>
++  string(4) "user"
++}
++string(4) "key3"
++array(1) {
++  ["type"]=>
++  string(4) "user"
++}
++string(4) "key4"
++array(1) {
++  ["type"]=>
++  string(4) "user"
++}
++string(4) "key5"
++array(1) {
++  ["type"]=>
++  string(4) "user"
++}
++string(4) "key6"
++array(1) {
++  ["type"]=>
++  string(4) "user"
++}
++string(4) "key7"
++array(1) {
++  ["type"]=>
++  string(4) "user"
++}
++string(4) "key8"
++array(1) {
++  ["type"]=>
++  string(4) "user"
++}
++string(4) "key9"
++array(1) {
++  ["type"]=>
++  string(4) "user"
++}
++string(5) "key10"
++array(1) {
++  ["type"]=>
++  string(4) "user"
++}
++============================
++
++IT #1
++============================
++string(4) "key0"
++array(1) {
++  ["key"]=>
++  string(4) "key0"
++}
++string(4) "key1"
++array(1) {
++  ["key"]=>
++  string(4) "key1"
++}
++string(4) "key2"
++array(1) {
++  ["key"]=>
++  string(4) "key2"
++}
++string(4) "key3"
++array(1) {
++  ["key"]=>
++  string(4) "key3"
++}
++string(4) "key4"
++array(1) {
++  ["key"]=>
++  string(4) "key4"
++}
++string(4) "key5"
++array(1) {
++  ["key"]=>
++  string(4) "key5"
 +}
-+object(foo)#%d (0) {
++string(4) "key6"
++array(1) {
++  ["key"]=>
++  string(4) "key6"
++}
++string(4) "key7"
++array(1) {
++  ["key"]=>
++  string(4) "key7"
 +}
-+object(foo)#%d (1) {
-+  ["a"]=>
-+  bool(true)
++string(4) "key8"
++array(1) {
++  ["key"]=>
++  string(4) "key8"
 +}
-+object(baz)#%d (6) {
-+  ["pri:private"]=>
-+  string(3) "baz"
-+  ["pub"]=>
-+  string(3) "bar"
-+  ["pro:protected"]=>
-+  string(3) "bar"
-+  ["pri:private"]=>
-+  string(3) "bar"
-+  ["bar"]=>
-+  bool(true)
-+  ["baz"]=>
-+  bool(true)
++string(4) "key9"
++array(1) {
++  ["key"]=>
++  string(4) "key9"
 +}
-+object(baz)#%d (6) {
-+  ["pri:private"]=>
-+  string(3) "baz"
-+  ["pub"]=>
-+  string(3) "bar"
-+  ["pro:protected"]=>
-+  string(3) "bar"
-+  ["pri:private"]=>
-+  string(3) "mod"
-+  ["bar"]=>
-+  bool(true)
-+  ["baz"]=>
-+  bool(true)
++string(5) "key10"
++array(1) {
++  ["key"]=>
++  string(5) "key10"
 +}
-+object(baz)#%d (6) {
-+  ["pri:private"]=>
-+  string(3) "baz"
-+  ["pub"]=>
-+  string(3) "bar"
-+  ["pro:protected"]=>
-+  string(3) "bar"
-+  ["pri:private"]=>
-+  string(3) "mod"
-+  ["bar"]=>
-+  bool(true)
-+  ["baz"]=>
-+  bool(true)
++============================
++
++IT #2
++============================
++string(4) "key0"
++array(0) {
++}
++string(4) "key1"
++array(0) {
++}
++string(4) "key2"
++array(0) {
 +}
++string(4) "key3"
++array(0) {
++}
++string(4) "key4"
++array(0) {
++}
++string(4) "key5"
++array(0) {
++}
++string(4) "key6"
++array(0) {
++}
++string(4) "key7"
++array(0) {
++}
++string(4) "key8"
++array(0) {
++}
++string(4) "key9"
++array(0) {
++}
++string(5) "key10"
++array(0) {
++}
++============================
++
++IT #3
++============================
++string(4) "key0"
++array(0) {
++}
++string(4) "key1"
++array(0) {
++}
++string(4) "key2"
++array(0) {
++}
++string(4) "key3"
++array(0) {
++}
++string(4) "key4"
++array(0) {
++}
++string(4) "key5"
++array(0) {
++}
++string(4) "key6"
++array(0) {
++}
++string(4) "key7"
++array(0) {
++}
++string(4) "key8"
++array(0) {
++}
++string(4) "key9"
++array(0) {
++}
++string(5) "key10"
++array(0) {
++}
++============================
++
++IT #4
++============================
++string(4) "key0"
++array(0) {
++}
++string(4) "key1"
++array(0) {
++}
++string(4) "key2"
++array(0) {
++}
++string(4) "key3"
++array(0) {
++}
++string(4) "key4"
++array(0) {
++}
++string(4) "key5"
++array(0) {
++}
++string(4) "key6"
++array(0) {
++}
++string(4) "key7"
++array(0) {
++}
++string(4) "key8"
++array(0) {
++}
++string(4) "key9"
++array(0) {
++}
++string(5) "key10"
++array(0) {
++}
++============================
++
++IT #5
++============================
++string(4) "key0"
++array(1) {
++  ["value"]=>
++  string(6) "value0"
++}
++string(4) "key1"
++array(1) {
++  ["value"]=>
++  string(6) "value1"
++}
++string(4) "key2"
++array(1) {
++  ["value"]=>
++  string(6) "value2"
++}
++string(4) "key3"
++array(1) {
++  ["value"]=>
++  string(6) "value3"
++}
++string(4) "key4"
++array(1) {
++  ["value"]=>
++  string(6) "value4"
++}
++string(4) "key5"
++array(1) {
++  ["value"]=>
++  string(6) "value5"
++}
++string(4) "key6"
++array(1) {
++  ["value"]=>
++  string(6) "value6"
++}
++string(4) "key7"
++array(1) {
++  ["value"]=>
++  string(6) "value7"
++}
++string(4) "key8"
++array(1) {
++  ["value"]=>
++  string(6) "value8"
++}
++string(4) "key9"
++array(1) {
++  ["value"]=>
++  string(6) "value9"
++}
++string(5) "key10"
++array(1) {
++  ["value"]=>
++  string(7) "value10"
++}
++============================
++
++IT #6
++============================
++string(4) "key0"
++array(0) {
++}
++string(4) "key1"
++array(0) {
++}
++string(4) "key2"
++array(0) {
++}
++string(4) "key3"
++array(0) {
++}
++string(4) "key4"
++array(0) {
++}
++string(4) "key5"
++array(0) {
++}
++string(4) "key6"
++array(0) {
++}
++string(4) "key7"
++array(0) {
++}
++string(4) "key8"
++array(0) {
++}
++string(4) "key9"
++array(0) {
++}
++string(5) "key10"
++array(0) {
++}
++============================
++
++IT #7
++============================
++string(4) "key0"
++array(1) {
++  ["num_hits"]=>
++  int(0)
++}
++string(4) "key1"
++array(1) {
++  ["num_hits"]=>
++  int(0)
++}
++string(4) "key2"
++array(1) {
++  ["num_hits"]=>
++  int(0)
++}
++string(4) "key3"
++array(1) {
++  ["num_hits"]=>
++  int(0)
++}
++string(4) "key4"
++array(1) {
++  ["num_hits"]=>
++  int(0)
++}
++string(4) "key5"
++array(1) {
++  ["num_hits"]=>
++  int(0)
++}
++string(4) "key6"
++array(1) {
++  ["num_hits"]=>
++  int(0)
++}
++string(4) "key7"
++array(1) {
++  ["num_hits"]=>
++  int(0)
++}
++string(4) "key8"
++array(1) {
++  ["num_hits"]=>
++  int(0)
++}
++string(4) "key9"
++array(1) {
++  ["num_hits"]=>
++  int(0)
++}
++string(5) "key10"
++array(1) {
++  ["num_hits"]=>
++  int(0)
++}
++============================
++
++IT #8
++============================
++string(4) "key0"
++array(1) {
++  ["mtime"]=>
++  int(%d)
++}
++string(4) "key1"
++array(1) {
++  ["mtime"]=>
++  int(%d)
++}
++string(4) "key2"
++array(1) {
++  ["mtime"]=>
++  int(%d)
++}
++string(4) "key3"
++array(1) {
++  ["mtime"]=>
++  int(%d)
++}
++string(4) "key4"
++array(1) {
++  ["mtime"]=>
++  int(%d)
++}
++string(4) "key5"
++array(1) {
++  ["mtime"]=>
++  int(%d)
++}
++string(4) "key6"
++array(1) {
++  ["mtime"]=>
++  int(%d)
++}
++string(4) "key7"
++array(1) {
++  ["mtime"]=>
++  int(%d)
++}
++string(4) "key8"
++array(1) {
++  ["mtime"]=>
++  int(%d)
++}
++string(4) "key9"
++array(1) {
++  ["mtime"]=>
++  int(%d)
++}
++string(5) "key10"
++array(1) {
++  ["mtime"]=>
++  int(%d)
++}
++============================
++
++IT #9
++============================
++string(4) "key0"
++array(1) {
++  ["creation_time"]=>
++  int(%d)
++}
++string(4) "key1"
++array(1) {
++  ["creation_time"]=>
++  int(%d)
++}
++string(4) "key2"
++array(1) {
++  ["creation_time"]=>
++  int(%d)
++}
++string(4) "key3"
++array(1) {
++  ["creation_time"]=>
++  int(%d)
++}
++string(4) "key4"
++array(1) {
++  ["creation_time"]=>
++  int(%d)
++}
++string(4) "key5"
++array(1) {
++  ["creation_time"]=>
++  int(%d)
++}
++string(4) "key6"
++array(1) {
++  ["creation_time"]=>
++  int(%d)
++}
++string(4) "key7"
++array(1) {
++  ["creation_time"]=>
++  int(%d)
++}
++string(4) "key8"
++array(1) {
++  ["creation_time"]=>
++  int(%d)
++}
++string(4) "key9"
++array(1) {
++  ["creation_time"]=>
++  int(%d)
++}
++string(5) "key10"
++array(1) {
++  ["creation_time"]=>
++  int(%d)
++}
++============================
++
++IT #10
++============================
++string(4) "key0"
++array(1) {
++  ["deletion_time"]=>
++  int(0)
++}
++string(4) "key1"
++array(1) {
++  ["deletion_time"]=>
++  int(0)
++}
++string(4) "key2"
++array(1) {
++  ["deletion_time"]=>
++  int(0)
++}
++string(4) "key3"
++array(1) {
++  ["deletion_time"]=>
++  int(0)
++}
++string(4) "key4"
++array(1) {
++  ["deletion_time"]=>
++  int(0)
++}
++string(4) "key5"
++array(1) {
++  ["deletion_time"]=>
++  int(0)
++}
++string(4) "key6"
++array(1) {
++  ["deletion_time"]=>
++  int(0)
++}
++string(4) "key7"
++array(1) {
++  ["deletion_time"]=>
++  int(0)
++}
++string(4) "key8"
++array(1) {
++  ["deletion_time"]=>
++  int(0)
++}
++string(4) "key9"
++array(1) {
++  ["deletion_time"]=>
++  int(0)
++}
++string(5) "key10"
++array(1) {
++  ["deletion_time"]=>
++  int(0)
++}
++============================
++
++IT #11
++============================
++string(4) "key0"
++array(1) {
++  ["access_time"]=>
++  int(%d)
++}
++string(4) "key1"
++array(1) {
++  ["access_time"]=>
++  int(%d)
++}
++string(4) "key2"
++array(1) {
++  ["access_time"]=>
++  int(%d)
++}
++string(4) "key3"
++array(1) {
++  ["access_time"]=>
++  int(%d)
++}
++string(4) "key4"
++array(1) {
++  ["access_time"]=>
++  int(%d)
++}
++string(4) "key5"
++array(1) {
++  ["access_time"]=>
++  int(%d)
++}
++string(4) "key6"
++array(1) {
++  ["access_time"]=>
++  int(%d)
++}
++string(4) "key7"
++array(1) {
++  ["access_time"]=>
++  int(%d)
++}
++string(4) "key8"
++array(1) {
++  ["access_time"]=>
++  int(%d)
++}
++string(4) "key9"
++array(1) {
++  ["access_time"]=>
++  int(%d)
++}
++string(5) "key10"
++array(1) {
++  ["access_time"]=>
++  int(%d)
++}
++============================
++
++IT #12
++============================
++string(4) "key0"
++array(1) {
++  ["ref_count"]=>
++  int(0)
++}
++string(4) "key1"
++array(1) {
++  ["ref_count"]=>
++  int(0)
++}
++string(4) "key2"
++array(1) {
++  ["ref_count"]=>
++  int(0)
++}
++string(4) "key3"
++array(1) {
++  ["ref_count"]=>
++  int(0)
++}
++string(4) "key4"
++array(1) {
++  ["ref_count"]=>
++  int(0)
++}
++string(4) "key5"
++array(1) {
++  ["ref_count"]=>
++  int(0)
++}
++string(4) "key6"
++array(1) {
++  ["ref_count"]=>
++  int(0)
++}
++string(4) "key7"
++array(1) {
++  ["ref_count"]=>
++  int(0)
++}
++string(4) "key8"
++array(1) {
++  ["ref_count"]=>
++  int(0)
++}
++string(4) "key9"
++array(1) {
++  ["ref_count"]=>
++  int(0)
++}
++string(5) "key10"
++array(1) {
++  ["ref_count"]=>
++  int(0)
++}
++============================
++
++IT #13
++============================
++string(4) "key0"
++array(1) {
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key1"
++array(1) {
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key2"
++array(1) {
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key3"
++array(1) {
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key4"
++array(1) {
++  ["mem_size"]=>
++  int(580)
++}
++string(4) "key5"
++array(1) {
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key6"
++array(1) {
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key7"
++array(1) {
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key8"
++array(1) {
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key9"
++array(1) {
++  ["mem_size"]=>
++  int(%d)
++}
++string(5) "key10"
++array(1) {
++  ["mem_size"]=>
++  int(%d)
++}
++============================
++
++IT #14
++============================
++string(4) "key0"
++array(1) {
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key1"
++array(1) {
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key2"
++array(1) {
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key3"
++array(1) {
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key4"
++array(1) {
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key5"
++array(1) {
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key6"
++array(1) {
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key7"
++array(1) {
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key8"
++array(1) {
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key9"
++array(1) {
++  ["ttl"]=>
++  int(0)
++}
++string(5) "key10"
++array(1) {
++  ["ttl"]=>
++  int(0)
++}
++============================
++
++IT #15
++============================
++string(4) "key0"
++array(0) {
++}
++string(4) "key1"
++array(0) {
++}
++string(4) "key2"
++array(0) {
++}
++string(4) "key3"
++array(0) {
++}
++string(4) "key4"
++array(0) {
++}
++string(4) "key5"
++array(0) {
++}
++string(4) "key6"
++array(0) {
++}
++string(4) "key7"
++array(0) {
++}
++string(4) "key8"
++array(0) {
++}
++string(4) "key9"
++array(0) {
++}
++string(5) "key10"
++array(0) {
++}
++============================
++
++IT #16
++============================
++string(4) "key0"
++array(11) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key0"
++  ["value"]=>
++  string(6) "value0"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key1"
++array(11) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key1"
++  ["value"]=>
++  string(6) "value1"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key2"
++array(11) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key2"
++  ["value"]=>
++  string(6) "value2"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key3"
++array(11) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key3"
++  ["value"]=>
++  string(6) "value3"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key4"
++array(11) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key4"
++  ["value"]=>
++  string(6) "value4"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key5"
++array(11) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key5"
++  ["value"]=>
++  string(6) "value5"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key6"
++array(11) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key6"
++  ["value"]=>
++  string(6) "value6"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key7"
++array(11) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key7"
++  ["value"]=>
++  string(6) "value7"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key8"
++array(11) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key8"
++  ["value"]=>
++  string(6) "value8"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++  ["ttl"]=>
++  int(0)
++}
++string(4) "key9"
++array(11) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key9"
++  ["value"]=>
++  string(6) "value9"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++  ["ttl"]=>
++  int(0)
++}
++string(5) "key10"
++array(11) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(5) "key10"
++  ["value"]=>
++  string(7) "value10"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++  ["ttl"]=>
++  int(0)
++}
++============================
++
++IT #17
++============================
++string(4) "key0"
++array(10) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key0"
++  ["value"]=>
++  string(6) "value0"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key1"
++array(10) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key1"
++  ["value"]=>
++  string(6) "value1"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key2"
++array(10) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key2"
++  ["value"]=>
++  string(6) "value2"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key3"
++array(10) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key3"
++  ["value"]=>
++  string(6) "value3"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key4"
++array(10) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key4"
++  ["value"]=>
++  string(6) "value4"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key5"
++array(10) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key5"
++  ["value"]=>
++  string(6) "value5"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key6"
++array(10) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key6"
++  ["value"]=>
++  string(6) "value6"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key7"
++array(10) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key7"
++  ["value"]=>
++  string(6) "value7"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key8"
++array(10) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key8"
++  ["value"]=>
++  string(6) "value8"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key9"
++array(10) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(4) "key9"
++  ["value"]=>
++  string(6) "value9"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(5) "key10"
++array(10) {
++  ["type"]=>
++  string(4) "user"
++  ["key"]=>
++  string(5) "key10"
++  ["value"]=>
++  string(7) "value10"
++  ["num_hits"]=>
++  int(0)
++  ["mtime"]=>
++  int(%d)
++  ["creation_time"]=>
++  int(%d)
++  ["deletion_time"]=>
++  int(0)
++  ["access_time"]=>
++  int(%d)
++  ["ref_count"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++============================
++
++IT #18
++============================
++string(4) "key0"
++array(3) {
++  ["key"]=>
++  string(4) "key0"
++  ["num_hits"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key1"
++array(3) {
++  ["key"]=>
++  string(4) "key1"
++  ["num_hits"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key2"
++array(3) {
++  ["key"]=>
++  string(4) "key2"
++  ["num_hits"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key3"
++array(3) {
++  ["key"]=>
++  string(4) "key3"
++  ["num_hits"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key4"
++array(3) {
++  ["key"]=>
++  string(4) "key4"
++  ["num_hits"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key5"
++array(3) {
++  ["key"]=>
++  string(4) "key5"
++  ["num_hits"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key6"
++array(3) {
++  ["key"]=>
++  string(4) "key6"
++  ["num_hits"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key7"
++array(3) {
++  ["key"]=>
++  string(4) "key7"
++  ["num_hits"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key8"
++array(3) {
++  ["key"]=>
++  string(4) "key8"
++  ["num_hits"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(4) "key9"
++array(3) {
++  ["key"]=>
++  string(4) "key9"
++  ["num_hits"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++string(5) "key10"
++array(3) {
++  ["key"]=>
++  string(5) "key10"
++  ["num_hits"]=>
++  int(0)
++  ["mem_size"]=>
++  int(%d)
++}
++============================
++
 +===DONE===
-diff -ubrN php-5.2.5-orig/ext/apc/tests/skipif.inc php-5.2.5/ext/apc/tests/skipif.inc
---- php-5.2.5-orig/ext/apc/tests/skipif.inc    1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/tests/skipif.inc 2007-12-26 16:51:32.000000000 -0600
+diff -Naur php-5.3.1.orig/ext/apc/tests/iterator_007.phpt php-5.3.1/ext/apc/tests/iterator_007.phpt
+--- php-5.3.1.orig/ext/apc/tests/iterator_007.phpt     1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/iterator_007.phpt  1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,36 @@
++--TEST--
++APC: APCIterator Overwriting the ctor
++--SKIPIF--
++<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?>
++--INI--
++apc.enabled=1
++apc.enable_cli=1
++--FILE--
++<?php
++class foobar extends APCIterator {
++      public function __construct() {}
++}
++$obj = new foobar;
++var_dump(
++      $obj->rewind(),
++      $obj->current(),
++      $obj->key(),
++      $obj->next(),
++      $obj->valid(),
++      $obj->getTotalHits(),
++      $obj->getTotalSize(),
++      $obj->getTotalCount(),
++      apc_delete($obj)
++);
++?>
++--EXPECTF--
++bool(false)
++bool(false)
++bool(false)
++bool(false)
++bool(false)
++bool(false)
++bool(false)
++bool(false)
++bool(false)
++
+diff -Naur php-5.3.1.orig/ext/apc/tests/php_5_3_ns.inc php-5.3.1/ext/apc/tests/php_5_3_ns.inc
+--- php-5.3.1.orig/ext/apc/tests/php_5_3_ns.inc        1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/php_5_3_ns.inc     1970-01-01 10:13:08.000000000 +0100
+@@ -0,0 +1,18 @@
++<?php
++namespace Foo\Bar;
++
++function sort() {
++      $a = array(3,2,1,4);
++      \sort($a);  // global scoping
++      var_dump($a);
++      return "IT WORKS";
++}
++class Baz {
++      public $i = 1;
++      protected $f = 3.14;
++      private $s = "hello world";
++
++      public function foo() {
++              sort();
++      }
++}
+diff -Naur php-5.3.1.orig/ext/apc/tests/skipif.inc php-5.3.1/ext/apc/tests/skipif.inc
+--- php-5.3.1.orig/ext/apc/tests/skipif.inc    1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/tests/skipif.inc 1970-01-01 10:14:21.000000000 +0100
 @@ -0,0 +1,6 @@
 +<?php
 +
@@ -15464,9 +21232,9 @@ diff -ubrN php-5.2.5-orig/ext/apc/tests/skipif.inc php-5.2.5/ext/apc/tests/skipi
 +//if (!ini_get('apc.enabled')) die("skip apc not enabled");
 +
 +?>
-diff -ubrN php-5.2.5-orig/ext/apc/TODO php-5.2.5/ext/apc/TODO
---- php-5.2.5-orig/ext/apc/TODO        1969-12-31 18:00:00.000000000 -0600
-+++ php-5.2.5/ext/apc/TODO     2007-12-26 16:51:32.000000000 -0600
+diff -Naur php-5.3.1.orig/ext/apc/TODO php-5.3.1/ext/apc/TODO
+--- php-5.3.1.orig/ext/apc/TODO        1970-01-01 01:00:00.000000000 +0100
++++ php-5.3.1/ext/apc/TODO     1970-01-01 10:13:08.000000000 +0100
 @@ -0,0 +1,30 @@
 +Known Bugs
 +