]> granicus.if.org Git - php/commitdiff
MFB __DIR_ constant support
authorStanislav Malyshev <stas@php.net>
Tue, 12 Feb 2008 01:02:06 +0000 (01:02 +0000)
committerStanislav Malyshev <stas@php.net>
Tue, 12 Feb 2008 01:02:06 +0000 (01:02 +0000)
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_language_parser.y
Zend/zend_language_scanner.l

index 4fb8533e3b10432aa20ba05155e8137ac69791ff..49145461f1d3785f5f01730ffc6f6455cbcb8da3 100644 (file)
@@ -25,6 +25,7 @@
 #include "zend_constants.h"
 #include "zend_llist.h"
 #include "zend_API.h"
+#include "tsrm_virtual_cwd.h"
 
 ZEND_API zend_op_array *(*zend_compile_file)(zend_file_handle *file_handle, int type TSRMLS_DC);
 ZEND_API zend_op_array *(*zend_compile_string)(zval *source_string, char *filename TSRMLS_DC);
@@ -5471,6 +5472,194 @@ void zend_do_end_compilation(TSRMLS_D) /* {{{ */
 }
 /* }}} */
 
+/* {{{ zend_dirname
+   Returns directory name component of path */
+ZEND_API size_t zend_dirname(char *path, size_t len)
+{
+       register char *end = path + len - 1;
+       unsigned int len_adjust = 0;
+
+#ifdef PHP_WIN32
+       /* Note that on Win32 CWD is per drive (heritage from CP/M).
+        * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
+        */
+       if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) {
+               /* Skip over the drive spec (if any) so as not to change */
+               path += 2;
+               len_adjust += 2;
+               if (2 == len) {
+                       /* Return "c:" on Win32 for dirname("c:").
+                        * It would be more consistent to return "c:." 
+                        * but that would require making the string *longer*.
+                        */
+                       return len;
+               }
+       }
+#elif defined(NETWARE)
+       /*
+        * Find the first occurence of : from the left 
+        * move the path pointer to the position just after :
+        * increment the len_adjust to the length of path till colon character(inclusive)
+        * If there is no character beyond : simple return len
+        */
+       char *colonpos = NULL;
+       colonpos = strchr(path, ':');
+       if (colonpos != NULL) {
+               len_adjust = ((colonpos - path) + 1);
+               path += len_adjust;
+               if (len_adjust == len) {
+                       return len;
+               }
+    }
+#endif
+
+       if (len == 0) {
+               /* Illegal use of this function */
+               return 0;
+       }
+
+       /* Strip trailing slashes */
+       while (end >= path && IS_SLASH_P(end)) {
+               end--;
+       }
+       if (end < path) {
+               /* The path only contained slashes */
+               path[0] = DEFAULT_SLASH;
+               path[1] = '\0';
+               return 1 + len_adjust;
+       }
+
+       /* Strip filename */
+       while (end >= path && !IS_SLASH_P(end)) {
+               end--;
+       }
+       if (end < path) {
+               /* No slash found, therefore return '.' */
+#ifdef NETWARE
+               if (len_adjust == 0) {
+                       path[0] = '.';
+                       path[1] = '\0';
+                       return 1; //only one character
+               } else {
+                       path[0] = '\0';
+                       return len_adjust;
+               }
+#else
+               path[0] = '.';
+               path[1] = '\0';
+               return 1 + len_adjust;
+#endif
+       }
+
+       /* Strip slashes which came before the file name */
+       while (end >= path && IS_SLASH_P(end)) {
+               end--;
+       }
+       if (end < path) {
+               path[0] = DEFAULT_SLASH;
+               path[1] = '\0';
+               return 1 + len_adjust;
+       }
+       *(end+1) = '\0';
+
+       return (size_t)(end + 1 - path) + len_adjust;
+}
+/* }}} */
+/* {{{ zend_u_dirname
+   Returns directory name component of path */
+ZEND_API size_t zend_u_dirname(UChar *path, size_t len)
+{
+       register UChar *end = path + len - 1;
+       unsigned int len_adjust = 0;
+
+#ifdef PHP_WIN32
+       /* Note that on Win32 CWD is per drive (heritage from CP/M).
+        * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive.
+        */
+       if ((2 <= len) && u_isalpha((UChar32)path[0]) && ((UChar)0x3a /*':'*/ == path[1])) {
+               /* Skip over the drive spec (if any) so as not to change */
+               path += 2;
+               len_adjust += 2;
+               if (2 == len) {
+                       /* Return "c:" on Win32 for dirname("c:").
+                        * It would be more consistent to return "c:."
+                        * but that would require making the string *longer*.
+                        */
+                       return len;
+               }
+       }
+#elif defined(NETWARE)
+       /*
+        * Find the first occurence of : from the left
+        * move the path pointer to the position just after :
+        * increment the len_adjust to the length of path till colon character(inclusive)
+        * If there is no character beyond : simple return len
+        */
+       UChar *colonpos = NULL;
+       colonpos = u_strchr(path, (UChar) 0x3a /*':'*/);
+       if(colonpos != NULL) {
+               len_adjust = ((colonpos - path) + 1);
+               path += len_adjust;
+               if(len_adjust == len) {
+               return len;
+               }
+       }
+#endif
+
+       if (len == 0) {
+               /* Illegal use of this function */
+               return 0;
+       }
+
+       /* Strip trailing slashes */
+       while (end >= path && IS_U_SLASH_P(end)) {
+               end--;
+       }
+       if (end < path) {
+               /* The path only contained slashes */
+               path[0] = DEFAULT_U_SLASH;
+               path[1] = 0;
+               return 1 + len_adjust;
+       }
+
+       /* Strip filename */
+       while (end >= path && !IS_U_SLASH_P(end)) {
+               end--;
+       }
+       if (end < path) {
+               /* No slash found, therefore return '.' */
+#ifdef NETWARE
+               if(len_adjust == 0) {
+                       path[0] = (UChar) 0x2e /*'.'*/;
+                       path[1] = 0;
+                       return 1; //only one character
+               }
+               else {
+                       path[0] = 0;
+                       return len_adjust;
+               }
+#else
+               path[0] = (UChar) 0x2e /*'.'*/;
+               path[1] = 0;
+               return 1 + len_adjust;
+#endif
+       }
+
+       /* Strip slashes which came before the file name */
+       while (end >= path && IS_U_SLASH_P(end)) {
+               end--;
+       }
+       if (end < path) {
+               path[0] = DEFAULT_U_SLASH;
+               path[1] = 0;
+               return 1 + len_adjust;
+       }
+       *(end+1) = 0;
+
+       return (size_t)(end + 1 - path) + len_adjust;
+}
+/* }}} */
+
 /*
  * Local variables:
  * tab-width: 4
index 9c722b35c72e517c6415eeadec1f2df66a1d978f..beb91e69f3362ebb5d5602a0304b12b6aa532980 100644 (file)
@@ -601,6 +601,8 @@ ZEND_API zend_bool zend_is_auto_global(char *name, uint name_len TSRMLS_DC);
 ZEND_API zend_bool zend_u_is_auto_global(zend_uchar type, zstr name, uint name_len TSRMLS_DC);
 ZEND_API zend_bool zend_u_is_auto_global_ex(zend_uchar type, zstr name, uint name_len, zend_bool runtime, zend_auto_global **ret TSRMLS_DC);
 ZEND_API int zend_auto_global_disable_jit(char *varname, zend_uint varname_length TSRMLS_DC);
+ZEND_API size_t zend_dirname(char *path, size_t len);
+ZEND_API size_t zend_u_dirname(UChar *path, size_t len);
 
 int zendlex(znode *zendlval TSRMLS_DC);
 
index 135b07e833dc59c02d7e325c50ed11c07aa57270..cb1b920168b2ba4ea23f94acccf34118efa383b4 100644 (file)
 %token T_FUNC_C
 %token T_LINE
 %token T_FILE
+%token T_DIR
 %token T_COMMENT
 %token T_DOC_COMMENT
 %token T_OPEN_TAG
@@ -721,6 +722,7 @@ common_scalar:
        |       T_CONSTANT_ENCAPSED_STRING      { $$ = $1; }
        |       T_LINE                                          { $$ = $1; }
        |       T_FILE                                          { $$ = $1; }
+       |       T_DIR                                           { $$ = $1; }
        |       T_CLASS_C                                       { $$ = $1; }
        |       T_METHOD_C                                      { $$ = $1; }
        |       T_FUNC_C                                        { $$ = $1; }
index 85867595461394008f6ac5dbcbb4254dd986d877..12b152740a9b7326e250cb427fbbda8e24058955 100644 (file)
@@ -62,6 +62,8 @@
 #include "zend_API.h"
 #include "zend_strtod.h"
 #include "zend_unicode.h"
+#include "tsrm_virtual_cwd.h"
+#include "tsrm_config_common.h"
 
 #ifdef HAVE_STDARG_H
 # include <stdarg.h>
@@ -2031,6 +2033,33 @@ HEREDOC_CHARS       ("{"*([^$\n\r\\{]|("\\"[^\n\r]))|{HEREDOC_LITERAL_DOLLAR}|({
        return T_FILE;
 }
 
+<ST_IN_SCRIPTING>"__DIR__" {
+       char *filename = zend_get_compiled_filename(TSRMLS_C);
+       const size_t filename_len = strlen(filename);
+       char *dirname;
+
+       if (!filename) {
+               filename = "";
+       }
+
+       dirname = estrndup(filename, filename_len);
+       zend_dirname(dirname, filename_len);
+
+       if (strcmp(dirname, ".") == 0) {
+               dirname = erealloc(dirname, MAXPATHLEN);
+#if HAVE_GETCWD
+               VCWD_GETCWD(dirname, MAXPATHLEN);
+#elif HAVE_GETWD
+               VCWD_GETWD(dirname);
+#endif
+       }
+
+       zendlval->value.str.len = strlen(dirname);
+       zendlval->value.str.val = dirname;
+       zendlval->type = IS_STRING;
+       return T_DIR;
+}
+
 <ST_IN_SCRIPTING>"__NAMESPACE__" {
        if (CG(current_namespace)) {
                *zendlval = *CG(current_namespace);