From fd597dce1bc0e173740ee568534733ec08e6e4f9 Mon Sep 17 00:00:00 2001 From: Stanislav Malyshev Date: Tue, 12 Feb 2008 00:21:15 +0000 Subject: [PATCH] [DOC] Add compile-time __DIR__ constant which implements dirname(__FILE__) --- Zend/zend_compile.c | 92 ++++++++++++++++++++++++++++++++++++ Zend/zend_compile.h | 1 + Zend/zend_language_parser.y | 2 + Zend/zend_language_scanner.l | 29 ++++++++++++ ext/standard/string.c | 89 +--------------------------------- 5 files changed, 125 insertions(+), 88 deletions(-) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 8ca2402969..e739f18684 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -26,6 +26,7 @@ #include "zend_llist.h" #include "zend_API.h" #include "zend_exceptions.h" +#include "tsrm_virtual_cwd.h" #ifdef ZEND_MULTIBYTE #include "zend_multibyte.h" @@ -4944,6 +4945,97 @@ void zend_do_end_compilation(TSRMLS_D) /* {{{ */ } /* }}} */ +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; +} +/* }}} */ /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 91df3bfd33..fb87f5d8d2 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -570,6 +570,7 @@ void zend_auto_global_dtor(zend_auto_global *auto_global); ZEND_API int zend_register_auto_global(char *name, uint name_len, zend_auto_global_callback auto_global_callback TSRMLS_DC); ZEND_API zend_bool zend_is_auto_global(char *name, uint name_len 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); int zendlex(znode *zendlval TSRMLS_DC); diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index 8467581721..788d69dda3 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -132,6 +132,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 @@ -715,6 +716,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 34078fdda0..1f88f3b451 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_exceptions.h" +#include "tsrm_virtual_cwd.h" +#include "tsrm_config_common.h" #ifdef HAVE_STDARG_H # include @@ -1545,6 +1547,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); diff --git a/ext/standard/string.c b/ext/standard/string.c index 11ee543ab1..89298eb442 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -1444,94 +1444,7 @@ PHP_FUNCTION(basename) Returns directory name component of path */ PHPAPI size_t php_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; + return zend_dirname(path, len); } /* }}} */ -- 2.40.0