[DOC] Add compile-time __DIR__ constant which implements dirname(__FILE__)

This commit is contained in:
Stanislav Malyshev 2008-02-12 00:21:15 +00:00
parent cf07e941f1
commit fd597dce1b
5 changed files with 125 additions and 88 deletions

View File

@ -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

View File

@ -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);

View File

@ -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; }

View File

@ -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 <stdarg.h>
@ -1545,6 +1547,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);

View File

@ -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);
}
/* }}} */