From: Stanislav Malyshev Date: Tue, 12 Feb 2008 01:02:06 +0000 (+0000) Subject: MFB __DIR_ constant support X-Git-Tag: RELEASE_2_0_0a1~521 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=c38d56e371336f76dd66158d6d795a0a956d8a5d;p=php MFB __DIR_ constant support --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 4fb8533e3b..49145461f1 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -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 diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 9c722b35c7..beb91e69f3 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -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); diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 135b07e833..cb1b920168 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -133,6 +133,7 @@ %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; } diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l index 8586759546..12b152740a 100644 --- a/Zend/zend_language_scanner.l +++ b/Zend/zend_language_scanner.l @@ -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 @@ -2031,6 +2033,33 @@ HEREDOC_CHARS ("{"*([^$\n\r\\{]|("\\"[^\n\r]))|{HEREDOC_LITERAL_DOLLAR}|({ return T_FILE; } +"__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; +} + "__NAMESPACE__" { if (CG(current_namespace)) { *zendlval = *CG(current_namespace);