[PHP-DEV] Re: cvs: php-src(PHP_5_3) /ext/phar/tests ini_set.phpt

2008-12-10 Thread Gregory Beaver
Hannes Magnusson wrote:
 What about 5.2? I thought the extension was supposed to work fine
 there too (at least there are bunch of tests that skip with the reason
 needs 5.2). So you have three branches in pecl? HEAD, PHP_5_3 and
 PHP_5_2?
 (Not that fix is required in 5.2, everyone who did try this
 functionality ignored the obvious wrong return value and committed the
 tests as-is and now 5.2 is apparently in
 security/critical-bugfix-mode-only.)

We have 1 branch in pecl.  The source uses #ifdef for the 5.2-specific
stuff.  So, yes, this test will need to be split into two.

Don't you just love arbitrary changes? :)

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: cvs: php-src(PHP_5_3) /ext/phar/tests ini_set.phpt

2008-12-09 Thread Gregory Beaver
Hannes Magnusson wrote:
 bjori Tue Dec  9 13:02:40 2008 UTC
 
   Modified files:  (Branch: PHP_5_3)
 /php-src/ext/phar/tests   ini_set.phpt 
   Log:
   MFH: fix test
   
   
 http://cvs.php.net/viewvc.cgi/php-src/ext/phar/tests/ini_set.phpt?r1=1.4.2.1r2=1.4.2.2diff_format=u
 Index: php-src/ext/phar/tests/ini_set.phpt
 diff -u php-src/ext/phar/tests/ini_set.phpt:1.4.2.1 
 php-src/ext/phar/tests/ini_set.phpt:1.4.2.2
 --- php-src/ext/phar/tests/ini_set.phpt:1.4.2.1   Fri Aug  1 13:38:47 2008
 +++ php-src/ext/phar/tests/ini_set.phpt   Tue Dec  9 13:02:40 2008
 @@ -25,7 +25,7 @@
  string(1) 1
  string(1) 1
  string(1) 1
 -string(1) 1
 -string(1) 1
 +bool(false)
 +bool(false)
  string(1) 1
  string(1) 1

Hi,

Heads up: there have been several commits to ext/phar in php-src by
non-maintainers who did not merge to pecl/phar, and a couple to
pecl/phar that were not merged to php-src.

You have 2 choices.

1) merge that sucker
2) email all of the phar maintainers whenever you do a commit so we at
least know about it and can do the merge.

php-src/phar HEAD/PHP_5_3 and pecl/phar are intended to be 100% in sync.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] problem with include_path and write-based file functions

2008-12-09 Thread Gregory Beaver
Hi,

This bug:

http://bugs.php.net/bug.php?id=46680

uncovers 2 larger issues.

1) Where should a function like file_put_contents() create its file if
it doesn't already exist and FILE_USE_INCLUDE_PATH is specified?  The
test for this is ext/standard/file/file_put_contents_variation4.phpt and
a few others.

file_put_contents($filename, File in include path, FILE_USE_INCLUDE_PATH);

arbitrarily creates $filename in the first portion of include_path on
PHP 5.2, and arbitrarily creates $filename in cwd in PHP 5.3.  Of
course, if the file already exists in any of the include_path, both PHP
5.2 and 5.3 will overwrite it.

The same is true of fopen() in write mode.

2) Should file_get_contents()/fopen() in read mode fall back to current
directory if not found in include_path?  The test for this is
ext/standard/file/fopen_variation5.phpt and others

In PHP 5.2, the functions simply fail if the file does not exist in
include_path.  Thus if include_path does not contain ., the file is
not found.  In PHP 5.3, there is a fallback to check cwd for the file.

For #1 I think both PHP 5.2 and 5.3 are broken.  If you specify that a
file should be written to inside include_path, it should fail if no file
is found - allowing arbitrary file creation is just plain stupid and
also dangerous - include_path has no business being used to create a
file, it should only be used to find existing files.  In any case, I
think allowing include_path to be used at all for file modification is
horrendous, and think it should be deprecated and removed from PHP 6. 
We should simply add file_resolve_path() function which can be used to
locate a file.

?php
if ($path = file_resolve_path('somefile.txt')) {
file_put_contents($path, 'blah');
} else {
file_put_contents($someOtherPath, 'blah');
}
?

For #2 I think PHP 5.3 is broken, and the fallback to cwd should be
removed from php_resolve_path.

Comments?

Greg

P.S. the tests themselves should not create directories outside of their
tests/ subdirectory, and should use things like PATH_SEPARATOR, but
that's a minor issue

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: Namespace resolution rules has been changed?

2008-11-17 Thread Gregory Beaver
David Grudl wrote:
 Try to answer the question: what is the $obj instance of?
 
 namespace foo;
 $obj = $factory-loadClass('bar\class');

bar\class

dynamic class names are always FQN.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: Namespace resolution rules has been changed?

2008-11-15 Thread Gregory Beaver
Stan Vassilev | FM wrote:
 Hi Marcin,

 Stan also requested this, so it should be considered as a possibility.

 Personally, I would rather not introduce this land mine.  It requires
 the user to do an implicit prepending of namespace name (foo) to bar
 in the use statement as well as a translation of A, which could fast
 lead to unreadable code.

 It is probably best to simply require a fully qualified name where it is
 intended.  Thus

 1) require leading \ in use statements
 2) allow namespace\blah in use statements, as this is a valid fully
 qualified name.

 ?php
 namespace my\ns;

 // this is a better way to do the suggested use bar as A;
 use namespace\bar as A;
 use \bar as B;

 class mine extends \my\parentclass {}
 ?
 
 Greg, I can't spot where does your example differ from what I and Marcin
 suggested? Please explain.

I would not allow use blah\blah as bar;

 And there's one more pain point which I posted earlier on the list
 about, but now as I prepare my framework for 5.3 namespaces, I *really*
 feel the pain in practice: the inability to pass a class/function name
 without specifying it fully as a string.
 
 My suggestion was:   use foo\bar\baz as alias;$name = nameof alias;
 // $name == 'foo\bar\baz'

Are you aware of __NAMESPACE__?  Also, if you are using a lot of
external namespace names, you might consider simply defining constants:

namespace foo\bar\baz;
const ns = __NAMESPACE__;

then you can simply do

use foo\bar\baz;  $name = baz\ns;

I don't see a huge pressing need for nameof since the above is 3 extra
lines of code - total - per NS.

If this sounds good, I will add an example to the new docs
yet-to-be-committed.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: Namespace resolution rules has been changed?

2008-11-14 Thread Gregory Beaver
Marcin Kurzyna wrote:
 ?php
 
 namespace foo;
 
 use bar as A;   /// -resolves as A == \foo\bar
 use \bar as B;  /// -resolves as B == \bar
 
 ?

Hi Marcin,

Stan also requested this, so it should be considered as a possibility.

Personally, I would rather not introduce this land mine.  It requires
the user to do an implicit prepending of namespace name (foo) to bar
in the use statement as well as a translation of A, which could fast
lead to unreadable code.

It is probably best to simply require a fully qualified name where it is
intended.  Thus

1) require leading \ in use statements
2) allow namespace\blah in use statements, as this is a valid fully
qualified name.

?php
namespace my\ns;

// this is a better way to do the suggested use bar as A;
use namespace\bar as A;
use \bar as B;

class mine extends \my\parentclass {}
?

Stas, I'm sure you have an opinion on this?

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: Namespace resolution rules has been changed?

2008-11-10 Thread Gregory Beaver
Jaroslav Hanslík wrote:
 David Grudl napsal(a):
 Hello!

 This code leads to fatal error: Class 'Nette\Loaders\Nette\Object'. Is
 it a bug in current implementation or namespace resolution rules has
 been changed?

 namespace Nette;

 class Object

 {}

 namespace Nette\Loaders;

 class AutoLoader extends Nette\Object

 {}

 $obj = new AutoLoader;



 Thank you,
 David Grudl
 
 I'm maybe wrong but I think that namespace resolution rules has been
 changed. This should work:
 
 namespace Nette\Loaders;
 
 class AutoLoader extends \Nette\Object
 {}

Hi,

The resolution rules have changed in that way.  The reason was an
inconsistency:

?php
// Autoload extends Sub\Object
class Autoloader extends Sub\Object {}
// Another extends Object
class Another extends Object {}
?

versus this code:

?php
namespace Nette;
// Nette\Autoload extends Sub\Object
class Autoloader extends Sub\Object {}
// Nette\Another extends Nette\Object
class Another extends Object {}
?

The problem was that it isn't immediately clear why we would consider
Sub\Object to be the same as \Sub\Object, but Object to be
different from \Object inside a namespace context, but the same
outside a namespace context.

This is an important thing for developers of namespaced code to realize.
 The docs have been updated in my personal checkout of php-doc, and I am
revising them to make them clearer, and also waiting on a few other
details to make it into CVS before committing.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] karma request

2008-11-09 Thread Gregory Beaver
Hi,

I'd like to request karma for ZE in order to do minor bugfixes and
refactoring.  I have no intention to commit any feature changes or major
commits, and am perfectly happy writing patches for these to be reviewed
by the big guns.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [PATCH] bracketed namespace declarations

2008-11-08 Thread Gregory Beaver
Steph Fox wrote:
 Hey Greg,
 
 Remember, the patch I'm proposing would only be necessary for people
 using un-namespaced code combined with namespaced code (already a bad
 idea) *and* scattering use statements throughout the global code.
 
 If it's 'already a bad idea', why support it?

Many people want this support, and it is only a bad idea if the code is
designed this way.  If you are simply combining several files together,
it is a necessary feature.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] [PATCH] bracketed namespace declarations

2008-11-07 Thread Gregory Beaver
Hi,

Stas and company decided that they wanted namespaces to have two legal
syntax choices:

1) single namespace per file:

?php
namespace foo;
...
?

2) multiple namespaces per file:

?php
namespace foo1 {
}
namespace foo2 {
}
?

I've implemented these two syntax options in a patch found at
http://pear.php.net/~greg/bracketed.patch.txt based on earlier work of
Dmitry Stogov.

It turns out there are some tricky details to work out, especially with
regard to importing via use statements.  If we just allow global,
un-namespaced code, for instance, we could end up with this mess:

?php
use blah\blah;

$f = new blah;

namespace one {
 use foo\bar as blah;
 $a = new blah;
}

// what is this?
blah::hi();
?

Technically, you could argue that blah::hi() should resolve to
blah\blah::hi(), but it is very difficult to track and figure out what
blah means by eye.  Thus, in the patch I implemented, if bracketed
namespace declarations exist, global use statements are not allowed, but
must exist within namespace ns {} brackets.

This creates a problem - how do you combine namespaced and unnamespaced
code?  To solve this, I introduced the oft-suggested namespace {}
syntax for un-namespaced code.  Thus, the above script would become:

?php
namespace {
 use blah\blah;
 $f = new blah;
}
namespace one {
 use foo\bar as blah;
 $a = new blah;
}
namespace {
 use blah\blah;
 blah::hi();
}
?

Another important point is that imports specified by the use statement
disappear when we exit a namespace block.  This way, it is very easy to
combine un-namespaced code that uses namespaces, and namespaced code.

Also very important to note is that the namespace {} syntax is
optional for any code that does not import other things via the use
statement - its sole purpose is to provide a clear visual and logical
wrapper within which imports occur.

Thus, this is also legal:

?php
namespace newly\coded\stuff {
 class mine { ... }
}
// old stuff here
class PEAR { ... }
?

Lastly, if global code does make use of namespaces, but does not import
anything, it can also happily co-exist with bracketed namespace code:

?php
namespace ns {
 class mine { ... }
}

$a = new ns\mine;
// and so on
?

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [PATCH] bracketed namespace declarations

2008-11-07 Thread Gregory Beaver
Stan Vassilev | FM wrote:

 ?php
 // global, scope 1
 
 namespace { // global, scope 2 }
 
 // global, scope 1
 
 namespace { // global, scope 3 }
 
 // global, scope 1
 
 namespace foo\bar { // foo\bar, scope 4 }
 
 // global, scope 1
 ?

I am afraid I must shed my generally congenial public nature to express
a strong opinion:

This is a horribly complex idea Stan.  PHP's implementation of
namespaces do not define scope.  Once we open that Pandora's box, there
is no turning back.

Big time -1 from me.

Remember, the patch I'm proposing would only be necessary for people
using un-namespaced code combined with namespaced code (already a bad
idea) *and* scattering use statements throughout the global code.

Also, the *only* supported use case behind allowing multiple namespaces
per file is to allow people to mash pre-existing separate PHP files
together, and have them still compile.  Requiring brackets is designed
to make it more readable, and the use restriction furthers that goal.

I would have implemented this requiring all code to be encased in
namespace {} or namespace nsname {}, but that turned out to be virtually
impossible in the parser because of the need to also allow declare
statements outside namespace declarations

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Call it: allow reserved words in a class or not?

2008-11-06 Thread Gregory Beaver
Dan wrote:
 Quite.
 
 It does appear as though, as a group, that you're struggling with the entire
 concept of namespaces. As demonstrated by this discussion, the resolution
 issues, the separator farce, and so on.
 
 It may be due to weaknesses in the PHP engine as a whole, I don't know...
 but it strikes me that most of these issues should be trivial ones, or ones
 that could be eliminated simply by approaching language design decisions
 with some common sense.
 
 In .NET, I can stick an Array class into my own namespace, extending the
 System.Array type if I want to and use it in my code without issue. Why can
 I not do that here? Is it simply that you're so worried about backwards
 compatibility that you feel that you can't make the necessary changes to the
 language to implement something fully?

Hi Dan,

OSS = show us a working patch and we'll consider it.  Do this before
saying the issues should be trivial ones.

Not too long ago I spent a significant amount of time trying to make it
possible to use a few reserved words as method names or function names,
and the result was a patch that made the parser and lexer significantly
more complex, with lots of bugs that were very difficult to fix, and
some edge cases where parsing simply failed.

As an example of why your suggestion is not logically possible to
implement, what should the following code print, 1 or 2?

?php
namespace namespace\namespace;
function test(){echo 1\n;}

namespace namespace;
function test(){echo 2\n;}

echo namespace\test();
?

No human can tell whether you mean to call the
namespace\namespace\test() function, or simply to call the test()
function from the current namespace.  Do you really expect a machine to
do any better?

Please spend at least 2 minutes carefully trying to think of an edge
case before lamenting any feature in the language, otherwise your posts
kill your credibility on the list and are frankly nothing other than
annoying noise.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: 5.3+ build broken, see compile log

2008-11-05 Thread Gregory Beaver
Pierre Joye wrote:
 Hi,
 
 A commit in the last 24 hours breaks the builds:
 
 d:\php-sdk\snap_5_3\vc9\x86\snap53_vc9\zend\zend_vm_execute.h(2735) :
 error C2036: 'void *' : unknown size
 d:\php-sdk\snap_5_3\vc9\x86\snap53_vc9\zend\zend_vm_execute.h(10445) :
 error C2036: 'void *' : unknown size
 d:\php-sdk\snap_5_3\vc9\x86\snap53_vc9\zend\zend_vm_execute.h(17792) :
 error C2036: 'void *' : unknown size

Hi,

Unrelated to this windows compilation problem (thanks Felipe for the
quick fix), I'm concerned to see that I missed an example of opcode
modification.  We can't modify opcodes directly because of opcode
caches.  This code needs to be refactored slightly to either create the
needed stuff in compile-time and pass it in with ZEND_OP_DATA or one of
the unused op1/op2 (best) or run-time estrndup finagling (not so good).

Thanks for pointing this out Pierre.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: Namespace Resolution

2008-11-05 Thread Gregory Beaver
Lukas Kahwe Smith wrote:
 
 On 04.11.2008, at 18:43, Ryan Panning wrote:
 
 Just to make my post clear, I'm in favor of this approach for
 non-qualified calls in a namespace.

 1. global
 2. autoload
 3. fail
 
 
 A couple of us (Hannes, Stas, Derick, Matt Wilson and I) were just
 chatting on IRC and we all favor the following:
 
 1) ns 2) autoload (for classes) and global (for functions/constants) 3)
 fail
 
 So no fallback to the global namespace for classes, but fallback for all
 functions/constants (regardless of internal or not)

Independently, I made this patch yesterday to do what you're describing.

http://pear.php.net/~greg/resolv.patch.txt

It turns out that we already fallback to all global constants (not just
internal ones).  Only functions and classes were falling back to
internal-only.

Once someone reviews and commits we can focus solely on bugfixes for
namespaces and finally get out alpha3 within a week (my guesstimate,
based on what things look like).

Regarding the patch: it is minimal changes for class name resolution.
It only removes the lines that tell the engine to do fallback for
classes.  We may also want to remove the few lines of functionality that
does fallback to internal for classes in zend_fetch_class, but I'd
rather wait on that, and do a full review of the way those constants are
being used in ZEND_FETCH_CONSTANT and all the other 5 places constants
are resolved, as I recycled some constants, which could use some
renaming.  The patch also does not update any tests, some of which
should fail.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] fixing opcode modification in namespace implementation

2008-11-05 Thread Gregory Beaver
Hi,

I assigned this to helly arbitrarily, but wanted to make sure that Stas
and Dmitry also see it.  This should be fixed ASAP.  The opcode
modification was easy to fix, since we weren't using op1.  I also fixed
a cosmetic issue Dmitry wanted fixed, which was replacing the
non-verbose 1 and 2 used to identify namespace constant vs. namespace
function in zend_resolve_non_class_name() with #defines.

http://bugs.php.net/bug.php?id=46500
patch at http://pear.php.net/~greg/fix_ns1.patch.txt

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] namespace separator and whining

2008-11-04 Thread Gregory Beaver
Christian Schneider wrote:
 Lukas Kahwe Smith wrote:
 one could also do
 1) ns
 2) global
 3) autoload
 
 I'm in favour of this (if it avoids performance problems) as I don't see
 a problem with giving global priority over autoload.

Hi,

This is the current name resolution.  The problem is that:

?php
namespace foo;
$a = new Exception();
?

will instantiate foo::Exception only if the class already exists, but
will instantiate Exception otherwise.  This defeats autoload's purpose
for existing.  We've been over this before.  It's dangerous.

There is one essential difference between classes and
functions/constants: autoload.

The only time the question of load order and fallback becomes and issue
is when code is not explicitly loaded.  In other words, a developer who
is relying upon an external function will do this at some point before
calling the function:

?php
include 'path/to/code/containing/function/source.php';
?

In other words, PHP expects you to actually load the source of functions
or constants you're going to be using in advance of using it.

This, I believe, is a reasonable expectation.

Classes, however, do *not* share this same expectation, because
autoload's explicit purpose is to allow using classes *before* their
source has been loaded.

In other words, it is perfectly all right to have a different name
resolution for classes than we have for functions and constants because
of this different expectation.  It is dangerous to fallback for classes
prior to autoload, but it is not at all dangerous for
functions/constants because the expectation is different.

For this reason, the only resolution that we should be considering is:

classes:
1) try ns::class
2) autoload ns::class
3) fail

functions/constants:
1) try ns::function/ns::const
2) try internal function/const
3) fail.

Note that I say try internal because the only purpose behind allowing
this is to make it easier to use PHP's built-in functionality.  Any
userspace stuff should be specifically \prefixed or imported via use.
And (yes) we need import for functions.

Greg

P.S. my mail server has been down for almost a week, apologies to anyone
who is wondering why I haven't replied to your message, I probably
didn't get it.

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] namespace separator and whining

2008-11-04 Thread Gregory Beaver
Lukas Kahwe Smith wrote:
 
 On 04.11.2008, at 17:15, Gregory Beaver wrote:
 
 In other words, it is perfectly all right to have a different name
 resolution for classes than we have for functions and constants because
 of this different expectation.  It is dangerous to fallback for classes
 prior to autoload, but it is not at all dangerous for
 functions/constants because the expectation is different.
 
 To me the key question is do we want to let people overload global
 classes easily or are we mostly talking about convinience? Class names
 are typed quite seldom (and even in a few years down the road the bulk
 of PHP's features will be provided via functions), so I would not think
 that we really need to focus on convenience here.

OK, taking a step back.  Let's distill the two problems we're trying to
solve

1) namespaces provide encapsulation - a safe way to name things without
worrying about whether it will conflict with external code
2) accessing internal functionality - the most used stuff in PHP should
still be easy to use in namespaces.

#1 means that when using our code inside namespaces, when there is
ambiguity we want it to look for namespaced stuff first and foremost.
#2 means we want to be able to access stuff like strlen() and
array_map() without any monkey business.

The largest conflict between #1 and #2 happens with classes because of
autoload.  __autoload() is expensive from a performance standpoint, and
should not be called unnecessarily.

I posit that the most used stuff in PHP are internal functions (not
global userspace functions, not internal classes, not userspace classes)
and so this needs to be a priority.  In addition, there is already
confusion over things like:

?php
// which of these is a function?
$a = 1;
unset($a);
$a = key(array('hi' = 1));
include('oops.php');
?

so requiring a prefix for functions will lead to parse errors in user
code like:

?php
\include('oops.php');
?

so the best resolution for functions is:

1) ns\function
2) internal function

Classes are different (TM).

if we do:

1) ns\class
2) autoload ns\class
3) internal class

then this code has hidden performance hits:

?php
namespace foo;
include 'external_autoload.php';  // __autoload must be declared
unnamespaced
$a = new ArrayObject(array('hi')); // calls autoload unnecessarily
?

if we really mean the ArrayObject class and not the foo\ArrayObject
class.  Thus, the convenience of internal fallback has disadvantages
(major performance problems) that do not exist with functions or constants.

Notifying the user via E_NOTICE/E_STRICT/E_WHATEVER simply adds
annoyance, and introduces potential for behavior change.  For instance,
if a user decides to start using some external library that defines an
autoload when they didn't have it before, suddenly all of their code
throws E_NOTICEs every time an internal class name is referenced.  Or,
without the E_NOTICE, performance suddenly slows way down and the user
blames the external library.

If we do:

1) ns\class
2) internal class
3) autoload ns\class

then our code example fails in a more subtle way.  The ambiguity of
ArrayObject resolves always in favor of internal class ArrayObject,
which means that users have to always explicitly import namespaced
classes to avoid this problem.  Why is it a problem?

Let's say we're doing our own userspace implementation of PDO with a few
extensions, for a system where PDO is disabled:

?php
namespace Myproject;
class PDO {} // userspace implementation of PDO
?

now in another file:

?php
namespace Myproject;
$a = new PDO(...);
?

[note: this implementation depends on __autoload existing]

Now, if PDO extension is disabled, the above code will successfully
autoload Myproject\PDO.  Imagine that on an upgrade, PDO is enabled.
Now, the object instantiated is of class PDO, not Myproject\PDO.
Suddenly, there are subtle logic errors that creep in (not a fatal
error), but the code continues to operate normally.

This resolution is very dangerous, and is a clear violation of the
primary purpose of namespaces.

If we do this:

1) ns\class
2) autoload ns\class

we get a stronger E_NOTICE (fatal E_ERROR) when an internal class is
used without explicit import.  This is robust, easy to debug, and forces
good code without much pain.  Our example user above has no problems
with the external library, and changes need not be made after initial
coding.

By doing the resolution I've suggested (and Stas, incidentally, was the
first to suggest this):

classes:
1) ns\class
2) autoload ns\class
3) FAILBOAT

functions/constants:
1) ns\func or ns\const
2) internal func\const
3) FAILBOAT

We get the best of #1 and the best of #2, and it makes coding easier in
the long run.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: /endnamespacediscussion

2008-10-25 Thread Gregory Beaver
David Grudl wrote:
 I hope it is only very bad joke :-(
 
 
 namespace myNamespace;
 
 class theLoader
 {
function load($class) { ... }
 }
 
 
 // somewhere else
 spl_autoload_register(array(myNamespace\theLoader, load));
 - registers myNamespacetabheLoader::load()

Fortunately, there is a simple workaround:

spl_autoload_register(array('myNamespace\theLoader', 'load'));

or slightly less simple:

spl_autoload_register(array(myNamespace\\theLoader, load));

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] UltraSimple Namespace Solution

2008-10-18 Thread Gregory Beaver
Nathan Rixham wrote:
 seen. Personally though I'd love to see stas' #1 get implemented and
 - used for all functions in a namespace so..
 one::step::two(); //always static method of class
 one::step-two(); //always function of namespace.
 
 But it's still ambiguous (only in a rarely though) - if an object with a
 method two is assigned to the static variable of a class called one
 then problem comes back.

First of all, this is not going to happen (voted down).  Second of all

one::$step

is how static variables are accessed, not one::step.  So there is no
potential for conflict.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] my last attempt at sanity with namespaces

2008-10-16 Thread Gregory Beaver
Stanislav Malyshev wrote:
 Hi!

 Yes, but most times when there is conflict it will be between two
 sets of code. So importing someone else's namespace explicitly and
 giving it a new name is a good call IMHO.

 If you have two distinct sets of code, why you use same namespace for
 both of them? Namespaces are specifically designed so you could have
 different sets of code in different places.

 nb Stas - I asked the same question about warnings, Greg updated his
 proposal since then to answer it.

 As it is now, every call to class::method() not accompanied with use
 should produce E_WARNING. I do not think it is an acceptable situation
 - this would make code migration a nightmare, since even if you never
 use functions and never even have any chance for a conflict, you still
 have to insert hundreds of imports into your code, just to shut up the
 warnings. I don't think it is a good idea. Feature that you do not
 need, can not disable and have to work around is called bug. 
Hi Stas,

This is not what is proposed.  The E_WARNING is *only* on a name
conflict.  Please re-read or try the patch:

http://pear.php.net/~greg/resolve_conflict.patch.txt

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] namespaces sanity: addition to RFC explaining why Stas's proposal doesn't work

2008-10-15 Thread Gregory Beaver
Hi again,

I was asked to explain why I hadn't included ClassName-Method(); in the
list of ideas that solve the ambiguity problem.  I added a brief section
to the RFC that does so:

http://wiki.php.net/rfc/namespaceissues#why_stas_s_proposed_solution_doesn_t_work

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] turn off gcov for php 4.4?

2008-10-12 Thread Gregory Beaver
Hi all,

Isn't it time to retire PHP 4.4 in gcov.php.net?  It's just wasted
resources for that version

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] question on how to solve major stream filter design flaw

2008-10-11 Thread Gregory Beaver
Hi,

I'm grappling with a design flaw I just uncovered in stream filters, and
need some advice on how best to fix it.  The problem exists since the
introduction of stream filters, and has 3 parts.  2 of them can probably
be fixed safely in PHP 5.2+, but I think the third may require an
internal redesign of stream filters, and so would probably have to be
PHP 5.3+, even though it is a clear bugfix (Ilia, your opinion
appreciated on this).

The first part of the bug that I encountered is best described here:
http://bugs.php.net/bug.php?id=46026.  However, it is a deeper problem
than this, as the attempts to cache data is dangerous any time a stream
filter is attached to a stream.  I should also note that the patch in
this bug contains feature additions that would have to wait for PHP 5.3.

I ran into this problem because I was trying to use stream filters to
read in a bz2-compressed file within a zip archive in the phar
extension.  This was failing, and I first tracked the problem down to an
attempt by php_stream_filter_append to read in a bunch of data and cache
it, which caused more stuff to be passed into the bz2 decompress filter
than it could handle, making it barf.  After fixing this problem, I ran
into the problem described in the bug above because of
php_stream_fill_read_buffer doing the same thing when I tried to read
the data, because I requested it return 176 decompressed bytes, and so
php_stream_read passed in 176 bytes to the decompress filter.  Only 144
of those bytes were actually bz2-compressed data, and so the filter
barfed upon trying to decompress the remaining data (same as bug #46026,
found differently).

You can probably tell from my explanation that this is an
extraordinarily complex problem.  There's 3 inter-related problems here:

1) bz2 (and zlib) stream filter should stop trying to decompress when it
reaches the stream end regardless of how many bytes it is told to
decompress (easy to fix)
2) it is never safe to cache read data when a read stream filter is
appended, as there is no safe way to determine in advance how much of
the stream can be safely filtered. (would be easy to fix if it weren't
for #3)
3) there is no clear way to request that a certain number of filtered
bytes be returned from a stream, versus how many unfiltered bytes should
be passed into the stream. (very hard to fix without design change)

I need some advice on #3 from the original designers of stream filters
and streams, as well as any experts who have dealt with this kind of
problem in other contexts.  In this situation, should we expect stream
filters to always stop filtering if they reach the end of valid input? 
Even in this situation, there is potential that less data is available
than passed in.  A clear example would be if we requested only 170
bytes.  144 of those bytes would be passed in as the complete compressed
data, and bz2.decompress would decompress all of it to 176 bytes.  170
of those bytes would be returned from php_stream_read, and 6 would have
to be placed in a cache for future reads.  Thus, there would need to be
some way of marking the cache as valid because of this logic path:

?php
$a = fopen('blah.zip');
fseek($a, 132); // fills read buffer with unfiltered data
stream_filter_append($a, 'bzip2.decompress'); // clears read buffer cache
$b = fread($a, 170); // fills read buffer cache with 6 bytes
fseek($a, 3, SEEK_CUR); // this should seek within the filtered data
read buffer cache
stream_filter_append($a, 'zlib.inflate');
?

The question is what should happen when we append the second filter
'zlib.inflate' to filter the filtered data?  If we clear the read buffer
as we did in the first case, it will result in lost data.  So, let's
assume we preserve the read buffer.  Then, if we perform:

?php
$c = fread($a, 7);
?

and assume the remaining 3 bytes expand to 8 bytes, how should the read
buffer cache be handled?  Should the first 3 bytes still be the filtered
bzip2 decompressed data, and the last 3 replaced with the 8 bytes of
decompressed zlib data?

Basically, I am wondering if perhaps we need to implement a read buffer
cache for each stream filter.  This could solve our problem, I think. 
The data would be stored like so:

stream: 170 bytes of unfiltered data, and a pointer to byte 145 as the
next byte for php_stream_read()
bzip2.decompress filter: 176 bytes of decompressed bzip2 data, and a
pointer to byte 171 as the next byte for php_stream_read()
zlib.inflate filter: 8 bytes of decompressed zlib data, and a pointer to
byte 8 as the next byte for php_stream_read()

This way, we would essentially have a stack of stream data.  If the zlib
filter were then removed, we could back up to the bzip2 filter and so
on.  This will allow proper read cache filling, and remove the weird
ambiguities that are apparent in a filtered stream.  I don't think we
would need to worry about backwards compatibility here, as the most
common use case would be unaffected by this change, and the use case it

Re: [PHP-DEV] question on how to solve major stream filter design flaw

2008-10-11 Thread Gregory Beaver
Marcus Boerger wrote:
 The filters need an input state and an output state. And they need to
 respect the the fact that number of requested bytes does not necessarily
 mean reading the same amount of data on the other end. In fact the output
 side does generally not know whether less, the same amount or more input is
 to be read. But this can be dealt with inside the filter. However the
 filters should return the number input vs the number of output filters
 always independently. Regarding states we would be interested if reaching
 EOD on the input state meant reaching EOD on the output side prior to the
 requested amount, at the requested amount or not at all yet (more data
 available).

Hi,

All of this makes sense, but how to implement it?  Currently, there is
no clear way to answer questions like:

1) how much data did the filter consume, and how much is left over?
2) how much data is left in the original stream prior to filtering?

Perhaps this could be implemented by overloading ftell() so that it can
accept a filter resource as well as a stream resource?  Also, a new
function could be implemented:

stream_filter_datasize(resource $filter) // I'm open to better names

that would either return the total size of filtered data available, or
false if this is indeterminate.  This would allow:

?php
$startoffile = 123;
$a = fopen('blah.zip');
fseek($a, $startoffile);
$filter = stream_filter_append($a, 'bzip2.decompress');
$b = fread($a, 170);
echo ftell($a),, ,ftell($filter),,
,stream_filter_datasize($filter),\n;
// outputs 145, 170, 176
?

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] namespace issues

2008-10-01 Thread Gregory Beaver
Vesselin Kenashkov wrote:
 I'm -1 for removing constants and functions from the namespaces. As I
 wrote already in another thread, is it possible to have a fatal error thrown
 when the engine detects an ambiguity situation? Are there any logical (i
 mean from OOP point of view) or internals (performance and so on) problems
 with this solution? In my opinion is better than dropping funcs  consts.

Hi,

There are problems with the internal implementation.  For instance,
constants do not store the line number on which they were created, and
are not actually registered as existing until runtime, so conflict
checks would happen at runtime.  This would mean your application could
work perfectly until a rarely executed branch of code is accessed and
boom, fatal error.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: Disable PHAR by default

2008-09-29 Thread Gregory Beaver
Jani Taskinen wrote:
 Seems like PHAR causes quite unexpected things, f.e.
 http://bugs.php.net/bug.php?id=46194 where PHP crashes if file does not
 exist. Please, can this crap be disabled by default (ALWAYS) and only
 those who actually need it can enable it?

Hi Jani,

Classic overreacting, and disrespect to years of careful work.

First of all, this bug has existed for all of 10 hours, and the problem
is easy to fix, and caused because I never imagined PHP would be stupid
enough to pass in a null pointer to zend_compile_file (kind of hard to
compile a file whose name is undefined).

This is a 3-line fix, and is only caused by a bug in the CGI handler
coupled with lighttpd, which is setting filename to 0x0, something none
of the other sapis do when a file is non-existent.

Let's think about this for a second: why pass in a null pointer for a
filename to a function whose purpose is to compile a file in the first
place?

How about we disable the CGI sapi under lighttpd by default?

Don't be such a weenie.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] true namespaces, yet another point of view

2008-09-28 Thread Gregory Beaver
Lukas Kahwe Smith wrote:
 
 On 24.09.2008, at 01:17, Guilherme Blanco wrote:
 
 For those that do not understand very well the explanation of jvlad...

 He's suggesting to change the class struct to be an scope struct, and
 have a property that tells if it's a namespace or a class, and reuse
 the implementation of class which already works very well.
 The nested support is achieved afai understand through the Adjacency
 List algorithm... can you confirm this to me?
 
 
 or just leave the organization of things to classes (with long class
 names with a nice prefix to prevent collissions) and leave it to
 class_alias() (and equivalent features for functions .. also with the
 option of a compile time aliasing) to handle the aliasing.
 
 this removes the need for namespaces and use statements, while making it
 possible to make class/function names short (that are long for
 organizational and collision prevention reasons).

Hi,

This approach doesn't work because aliasing with class_alias() does not
allow name conflicts:

?php
class foo {
function __construct(){echo 'hi',\n;}}
class_alias('foo', 'XMLReader');
$a = new XMLReader;
?

results in:

Warning: Cannot redeclare class XMLReader in
/home/cellog/workspace/php5/test.php on line 4

whereas:

?php
class foo {
function __construct(){echo 'hi',\n;}}
use ::foo as XMLReader;
$a = new XMLReader;
?

results in:

hi

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] solving the namespace conflict issues betweenfunction/staticmethod class constant/ns constant

2008-09-28 Thread Gregory Beaver
Daniel Convissor wrote:
 On Mon, Sep 22, 2008 at 08:07:10PM +0400, Dmitry Stogov wrote:
 
 Yes. Changing :: into any other separator solves the functions/static
 methods and constants ambiguity, but it also breaks intuitive syntax.
 
 Which is more important?  Considering there have been threads upon 
 threads filled with myriad messages, it seems resolving the ambiguity is 
 significanly more important than an intuitive syntax.
 
 Please, let's pick a different operator for namespaces.  This will 
 eliminate the scoping/resolution issues for both the engine and the 
 humans trying to interpret PHP code.
 
 [/me searching for the vote tally on which operator people preferred]
 [/me alas, can't find it at the moment]
 
 I recall there being a vote on this.  I'm sure some of you have a saved 
 copy and/or link to it.  Can't we pick the operator on that list that got 
 the second highest vote count?

Hi,

The second highest vote was :::, but there was strong objection to this
as well from some.  The problem, I still believe, is that we are focused
on having the same:::stupid:::operator:::between:::everything.

The truth is that in source files, there is a clear boundary between
namespace definition as in:

?php
namespace foo::bar;
?

and the things in the namespace, as in:

?php
class bar {}
?

Without context, the above definition of class bar could define
literally any class name:

bar
something::bar
another::long::name::bar

depending on the namespace declaration at the top of the file.  This
means that it is an arbitrary choice in the current implementation to
use :: to join the two things (namespace name and class name).

In truth, it will be a lot easier to debug code if this is a different
separator, as the boundary between namespace and element will be crystal
clear.  For instance:

(current implementation)
my::framework::someFunction()-aProperty-someMethod();

is my::framework a class or a namespace?

Let's use an arbitrary separator .. to mark the boundary between
namespace and class/function

(new implementation)
my::framework..someFunction()-aProperty-someMethod();

OK, now we know that my::namespace is a namespace, and someFunction is a
function.

my..framework::someFunction()-aProperty-someMethod();

The above is also clear: my is a namespace, framework is a class name,
and someFunction is a static method.

This has the advantage that existing code based on PHP 5.3 alpha 1 and 2
won't require very much modification, it is easy to read, and easy to
understand what a line of code does without needing any context information.

I took my old patch and moved from the - separator to the .. separator
in about 45 minutes of work, so changing the separator will not be
difficult.  Here's the new patch against PHP_5_3:

http://pear.php.net/~greg/ns.element.2.patch.txt

Unlike the first patch, it introduces a new token, T_NS_MEMBER, instead
of recycling T_OBJECT_OPERATOR.

This is also easy to document.  Here's how I would do it:

Although namespaces can span multiple files, they are similar to static
classes.

Namespaces are used in PHP to link related classes, functions, and
constants much as static classes can be used to link related variables,
methods, and constants.

The classes, functions, and constants defined in a namespace are called
namespace elements just as the variables, methods and constants
defined in a static class are static class members

A static class example:

?php
class myclass
{
const one = 1;
static public $a;
static function show()
{
echo __METHOD__,\n;
}
}

myclass::show();
$variable = myclass::$a;
echo myclass::one;
?

Static class members can be accessed using the :: operator, as in
myclass::show().

Here is a namespace example:

file1.php:
?php
namespace mynamespace;
const one = 1;
function show()
{
echo __FUNCTION__,\n;
}
class myclass
{
function show()
{
echo __METHOD__,\n;
}
}
class mystaticclass
{
static function show()
{
echo __METHOD__,\n;
}
}
?

main.php:
?php
include 'file1.php';

mynamespace..show();
echo mynamespace..one;
$a = new mynamespace..myclass;
$a-show();
?

Namespace elements can be accessed using the .. operator, as in
mynamespace..show().

Another example showing how to access static class members within a
namespace:

?php
include 'file1.php';
mynamespace..mystaticclass::show();
?

Namespaces can be nested using the :: operator as in:

file2.php:
?php
namespace my::nested::ns;
class mystaticclass
{
static function show()
{
echo __METHOD__,\n;
}
}
?

The use statement allows importing both namespace elements and
namespace names into the current scope:

?php
include 'file1.php';
incldue 'file2.php';

use mynamespace..mystaticclass;
use my::nested::ns;
use my::nested;
use my::nested::ns..mystaticclass as myclass;

mystaticclass::show(); // mynamespace..mystaticclass::show()
myclass::show(); // my::nested::ns..mystaticclass::show()
ns..mystaticclass::show(); // 

Re: [PHP-DEV] alpha3

2008-09-27 Thread Gregory Beaver
jvlad wrote:
 Adding support for functions, constants and even variables is actually
 quite do-able with the solution I suggested (different separator between
 namespace name and function/constant/variable name) and can be added 
 easily.
 
 Adding support for functions, constants and even variables is actually
 quite do-able with the solution I suggested (different separator between
 namespace name and function/constant/variable name) and can be added 
 easily.
 
 
 Greg,
 
 Does it mean that the namespace separator will not be (or likely not to be) 
 the same when you need access to namespaced classes vs namespaced functions? 
 What's about consistency of the design? If you can't resolve the ambiguity 
 or any other problems around namespaces without changing the separator, why 
 not to change it for classes too?

Hi,

The patch I posted here:

http://pear.php.net/~greg/ns.element.patch.txt

does exactly what you are talking about.  For some reason, some people
find this too difficult to digest.  I've already expressed my opinion on
the matter (after all, I did spend almost a week developing the patch).

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] solving the namespace conflict issues between function/staticmethod class constant/ns constant

2008-09-22 Thread Gregory Beaver
Dmitry Stogov wrote:
 Hi Greg,

 Greg Beaver wrote:
   
 Lupus Michaelis wrote:
 
 Larry Garfield a écrit :

   
 I agree that #5 seems like the best solution.  The problem is caused
 by the double meaning of ::.  All of the other solutions feel like
 bandaids.  
 
   They are not a double meaning : it is a scope resolver. Like in C++.
 So please all stop this war about namespaces, and look where it was
 resolved in other languages. It will be wisely :)
   
 Hi,

 Amazingly enough, this work has already been done.  The first thing
 noticed is that C++ is a compiling language, and PHP isn't.  Therefore
 at compile time, it is possible to know every single file that will be
 available, every single class, and so on.  This enables all kinds of
 clever resolution such as importing ns::* and it actually works with
 full performance.

 PHP, on the other hand, is a dynamic language, and it is impossible to
 know in advance which files, which classes, which namespaces will be
 defined.  Other dynamic languages that have implemented namespaces have
 solved the problems mentioned via run-time resolution, which is much slower.

 One key difference from C++ is that namespaces do *not* define scope in
 PHP.  The only constructs that define scope different from global scope
 are functions and now closures (as I understand them from reading the
 mailing list).

 I suppose I should have mentioned option #6: do all class, function and
 constant resolution at run-time, obsoleting all opcode caches and make
 PHP 5.3 an unusable release for any high traffic websites.
 

 Please check your suggestions before publishing them.

 ?php
 class Foo {
 function bar() {
 }
 }

 function simplecall() {
   for ($i = 0; $i  100; $i++) {
   Foo::bar();
   Foo::bar();
   Foo::bar();
   Foo::bar();
   Foo::bar();
   Foo::bar();
   Foo::bar();
   Foo::bar();
   Foo::bar();
   Foo::bar();
   }
 }

 simplecall();
 ?

snip

hi Dmitry,

Let me quote myself from right above your reply:

option #6: do all class, function and constant resolution at run-time

This would be slow and eliminate most of the benefit of opcode caches. 
The script you posted does not demonstrate option #6 because that's not
how PHP works or has ever worked.  Which suggestion are you trying to
debunk?

I was never saying the current implementation is slow, only that it is
broken.  Without changes, it is dangerous in PHP's namespace
implementation to

1) ever use short names inside a namespace declaration for any class in
the same namespace not defined in the same file
2) mix functions and classes in the same project with hierarchical
namespace declarations, or mix namespace constants with class constants

#1 makes namespaces essentially more verbose than the existing situation
(:: is longer than _), and #2 requires users to perform more diligence
than they would have to before namespaces.  In both cases, this either
introduces more chance for subtle logic failure compared to PHP prior to
namespaces, or requires longer class names.  I highly doubt that is the
intention.

Returning to the original debate, if you really believe this conflict is
not an issue, then why was the first user note published last December a
note about this conflict?

http://us3.php.net/manual/en/language.namespaces.php#80035

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] solving the namespace conflict issues between function/static method class constant/ns constant

2008-09-20 Thread Gregory Beaver
Larry Garfield wrote:
 On Saturday 20 September 2008 6:43:41 pm Richard Quadling wrote:
 
 5) a simply syntax change to namespaces, introducing a new concept:
 namespace element.

 A namespace element is a class, function or constant defined within a
 namespace declaration:

 ?php
 namespace foo;
 class bar {} // class element bar in namespace foo
 function bar(){} // function element bar in namespace foo
 const bar=1; // const element bar in namespace foo
 ?

 This is similar to class elements:

 ?php
 class foo {
 function bar(){} // method element bar in class foo
 const bar=1; // constant element bar in class foo
 public $bar=1; // variable element bar in class foo
 }
 ?

 Currently, this code:

 ?php
 namespace foo::bar;
 class buh{}
 ?

 creates a class named foo::bar::buh, essentially joining the namespace
 foo::bar and its class element buh with the separator ::.  This
 turns out to be the root of the problem with the conflicts between class
 elements and namespace elements.  The last patch introduces a new
 namespace element operator to delineate the boundary between namespace
 name and element name. For the patch, I recycled T_OBJECT_OPERATOR (-).

 current way:
 ?php
 foo::bar-test(); // namespace foo::bar, call to function element test()
 foo-bar::test(); // namespace foo, call to static method element test()
 in class element bar
 foo-myconst; // namespace foo constant myconst
 foo::myconst; // class foo constant myconst
 ?

 The patch is at:

 http://pear.php.net/~greg/ns.element.patch.txt

 This is the most extensive change.  The patch preserves :: as global
 element accessor (::strlen() calls strlen internal function, for
 instance).  I'm happy to answer any other questions.

[snip]

 I agree that #5 seems like the best solution.  The problem is caused by the 
 double meaning of ::.  All of the other solutions feel like bandaids.  
 
 Of course, the problem then is finding a symbol that is not already used.  I 
 don't think reusing - is any wiser than reusing ::.  # would be great if it 

Let's be clear.  Here is a sample of code with the new syntax:

?php
namespace name::still::has::double::colon;
const oscopy = 1;
class blow{
const byblow = 1;
static function hard(){}
}

namespace another::name;
use name::still::has::double::colon;

// fully qualified name:
// note that - is only used once
// to specify the boundary between namespace name and namespace member.
$a = new name::still::has::double::colon-blow;
$a = new colon-blow;
// static method call
colon-blow::hard();
// or
name::still::has::double::colon-blow::hard();

// ns constant
echo colon-oscopy;

namespace blow;
function hard(){}

namespace a::third::name;
// demonstrate importing a class name
// which is different from importing a namespace name
use name::still::has::double::colon-blow;

// class static method
blow::hard();
// namespace function
::blow-hard();
// class constant
echo blow::byblow;
?

Two important things to note:
 - ambiguity between namespace name and class name is eliminated
?php
namespace foo;
class test{
}
namespace foo::test;
class test{}
namespace third;
use foo::test;
$a = new test;  // this is namespace foo, class test
$a = new test::test; // this is namespace foo::test, class test
?
 - this separator is self-documenting.  One does not need to grep source
code to determine whether blah-thing is a namespaced function or a
static method of class blah.  The same is true of use statements.  It is
crystal clear whether we are importing a namespace or a class name.
This will make debugging someone else's code a lot easier than it
otherwise would be.

Jochem has informed me he is taking care of the wiki RFC for this stuff.
 I am allergic to wikis, unfortunately.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: Namespaced function vs static method in global class

2008-09-16 Thread Gregory Beaver
Ionut Gabriel Stan wrote:

snip

 echo Test::foo(); // outputs namespace function
 echo 'br';
 echo ::Test::foo(); // outputs namespace function

snip

 My questions are:
 
 1. How should I call the static method foo in the global class Test (except 
 for call_user_func)
 2. How should I call the static method baz of class Bar in namespace Test 
 with call_user_func
 3. Is there no possibility to change your minds and replace the double colon 
 with something else, likes a simple colon? I find it very confusing to figure 
 out what is what and the way I should call it.

Hi Ionut,

Stas did a good job of answering how to call the static method using
call_user_func.  The answer to #1 under the current implementation is
you can't which is why I posted a patch to allow differentiating
between the two earlier this week.

However, I have since discovered a much better solution, and have a
working patch, but am checking details offlist before I propose it, as
it involves a slight but important change to namespace syntax.  Stay
tuned for further details.  As for your 3rd question, I guarantee this
will not happen, as it is technically impossible to do.  For instance:

switch ($something) {
case oops:
is:this:part:of:oops();
break;
}

The above code could resolve to either case oops: followed by
is:this:part:of:oops() or as case oops:is:this:part:of:oops() and
there is no way for a computer to tell the difference without
introducing required whitespace.  Since PHP != Python, that won't happen :).

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: [PATCH] Re: [PHP-DEV] namespace examples (solving name resolutionorderissues)

2008-09-13 Thread Gregory Beaver
Stanislav Malyshev wrote:
 Hi!

 In other words, there is simply no comparison.  Userspace class usage
 outnumbers internal class usage by an order of magnitude in typical OO
 PHP code.

 I didn't claim userspace class usage outnumbers internal class usage
 or otherwise. What I claimed is that since we have a lot of files
 (framework has 1821, as you very helpfully pointed out) and those use
 950 instances of internals classes, application using Framework has
 big chance to score hundreds of uncacheable autoloads. And that is
 not counting user code, which would add to the problem.
Right, and since you pointed out this limitation and then found another
example that has the same problem that cannot be solved (non-autoload
with load order determining what classname is instantiated), that
invalidates any possible approach.  I was trying to say that this leaves
us with only 1 choice, which is whether to use the name resolution you
proposed or stick with the current one.  Currently we have:

1) check current namespace
2) check internal
3) autoload if possible
4) fail

I remind all of the name resolution for classes that you proposed:

1) check current namespace
2) autoload if possible
3) fail

Since my little script proved that the ratio of userspace vs. internal
classes heavily favors userspace classes, this load order makes sense. 
However, I want to point out that it doesn't take a script to prove that
the ratio of userspace functions vs. internal functions is exactly the
opposite (far more internal functions vs. userspace functions), so I
propose we have separate name resolution for classes and functions

classes:

1) check current namespace
2) autoload if possible
3) fail

functions:

1) check current namespace
2) check internal
3) fail

Load order would matter for functions, but the risk is worth the benefit.

I believe the initial implementation of namespaces had this order for
classes, so Dmitry's first patch would have the necessary changes.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: [PATCH] Re: [PHP-DEV] namespace examples (solving name resolutionorderissues)

2008-09-12 Thread Gregory Beaver
Stanislav Malyshev wrote:
 Hi!
 
 The caching is at runtime.  Basically, it's in executor_globals, and so
 is not linked to any opcode array (I couldn't figure out any other
 globally accessible storage location).  It works like an associative
 array.  If file X.php loads XMLReader in namespace namespacename, it
 creates this entry:

 array(
 'X.php\0namespacename::XMLReader' = {class entry for XMLReader}
 );
 
 I though a bit about that patch, and I see following problems with it:
 
 1. If you do not use autoloading, you still can get different
 resolution, e.g.:
 
 ?php
 namespace foo;
 $a = new XMLReader;
 
 resolves to ::XMLReader and cached for this file. But suppose some other
 file, somewhere, loaded foo::XMLReader prior to that. Then the same code
 here would resolve now to foo::XMLReader as before, right?
 Isn't it the same scenario you complained about? If so this patch does
 not solve this for 100% of cases, unless I misunderstand how the patch
 works.
 
 2. While the caching indeed helps per-file, typical OO application
 contains dozens of files, and each file may use dozens of internal
 classes (my install has 100+ internal classes). Meaning, there is still
 potential for hundreds of non-cacheable exhaustive autoload searches.
 This is not a good scenario.

Your first point is correct, and the second is interesting, but does not
quite match reality.  I whipped up a script to count the number of
internal vs. user classes in a project, it's at

http://pear.php.net/~greg/detect_classes.phps

I ran it on PEAR2, which is a pre-namespace project at the moment, and
came up with these stats:

Internal classes: 239
User classes: 768
in 171 files

I ran the same script over PEAR, and got:

Internal classes: 110
User classes: 2027
in 231 files

Now, you may argue that these are atypical OO applications, so I also
ran the script over Zend Framework 1.5, with these results:

Internal classes: 950
User classes: 16167
in 1821 files

In other words, there is simply no comparison.  Userspace class usage
outnumbers internal class usage by an order of magnitude in typical OO
PHP code.

PEAR2 uses an average of 2 internal classes per file, and 7 userspace
classes.  PEAR uses an average of 0.5 internal classes per file, and 8
userspace classes per file.  Zend Framework uses an average of 0.5
internal classes per file and ~9 userspace classes per file.  Thus, if I
had to choose between defaulting to current namespace (as you suggested)
and to internal classes, the choice is easy.  I would choose current
namespace because there would be far fewer use statements, and the
behavior is deterministic.

The script is at:

http://pear.php.net/~greg/detect_classes.phps

run with php detect_classes.php /path/to/files

Oh, and the script is one of the few cases where there are 3 internal
classes used and only 1 userspace class :).

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: [PATCH] Re: [PHP-DEV] namespace examples (solving name resolutionorder issues)

2008-09-11 Thread Gregory Beaver
Stas and I continued our discussion off list, and decided to pop it back
on the list, so here is 1 message, another to follow.

Greg

===
Stanislav Malyshev wrote:
  Hi!
 
  ...the message you replied to?
 
  I must be missing something here. In my last reply, I raised a number
  of points, including having unqualified names resolve only to
  namespace and relation of this to functions and constants. I do not
  see these points addressed or discussed anywhere in your email. Some
  less important points - like tradeoffs you need to take for working
  with internal classes (second reply part in my email) - weren't
  mentioned either.
Hi Stas,

In your last reply, you asserted that the only solution was to always
resolve unqualified names to namespace::name.  The patch I sent actually
shows that this is unnecessary.
 
  Also, I do not see the explanation how this patch is different from
  the last one and how the difference in the speed is achieved - you
  just claim it has gone from 466x to 5.2x but I did not find any
  explanation about what is the change allowed you to do this. I would
  like to understand what this change is and to do that from reading a
  patch is kind of hard and I can't be sure what I understood was
  actually your intent. Could you explain it?
  You could also contact me on IM or IRC if you prefer.
Basically, the patch does 2 things

1) resolution order is changed to:

foo.php:
$a = new foo();
a) does namespace::foo class exist?
b) try to autoload namespace::foo
c) try to locate internal class ::foo

2) if internal class ::foo is found, then cache this information so that
if another reference to the foo class occurs in foo.php, resolution
short circuits to:
a) use internal class ::foo

This second point is why the slowdown went from ridiculous to slight.

Since your primary complaint about the resolution order is performance,
and the patch removes the performance problem, this makes your
suggestion of never checking internal classes unnecessary.  That was the
point of my previous email with the patch.  Clear now?

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: [PATCH] Re: [PHP-DEV] namespace examples (solving name resolutionorder issues)

2008-09-11 Thread Gregory Beaver
Hi,

This is the 2nd of two exchanges that occurred off-list that Stas and I
would like to put back on-list.

Greg
===
Stanislav Malyshev wrote:
  Hi!
 
  Basically, the patch does 2 things
 
  1) resolution order is changed to:
 
  foo.php:
  $a = new foo();
  a) does namespace::foo class exist?
  b) try to autoload namespace::foo
  c) try to locate internal class ::foo
 
  2) if internal class ::foo is found, then cache this information
so that
  if another reference to the foo class occurs in foo.php, resolution
  short circuits to:
  a) use internal class ::foo
 
  This second point is why the slowdown went from ridiculous to slight.
 
  OK, now I understand better what it does, thanks. Do I understand
  right that the caching is in runtime, when the class access opcode is
  executed (since you couldn't autoload in compile time)? If so, how
  long the cache entry is kept there? I.e. if I have execution path that
  goes to file A, then B, then A again, then C, then B, etc. and then
  unroll the stack back - do I store all results for second entrance
  into A? Is it per-op-array (since we don't have per-file data
  structure AFAIK)? What happens if include path (or autoloader)
  changes, so that the class name that could not be loaded before can be
  loaded now - e.g. application adds plugin definitions, etc. - will it
  be ensured that autoloading is never attempted again for the same
  class? What happens if somebody loads that namespace::foo class
  manually (with require) - will the old resolution hold or the new one
  apply?
 
  Also I note that even if the cache stores all resolutions for all
  internal classes times all namespaces, it will still require at least
  one exhaustive autoload search per internal class per op-array - or
  per file, if you somehow find a way to store cache per-file in
  runtime, and these can not be eliminated with bytecode caching, unlike
  all other filesystem accesses.
Hi,

The caching is at runtime.  Basically, it's in executor_globals, and so
is not linked to any opcode array (I couldn't figure out any other
globally accessible storage location).  It works like an associative
array.  If file X.php loads XMLReader in namespace namespacename, it
creates this entry:

array(
'X.php\0namespacename::XMLReader' = {class entry for XMLReader}
);

So that the next time we reach X.php and the XMLReader class, it sees
this entry, and does not attempt autoload.  As for your questions about
include_path/autoload, I had not added this to the patch, but the easy
solution is to clean the hash on include_path change, or autoload
change.  I assume this code would break with the patch:

sneakyreader.php:
?php
namespace foo;
class XMLReader {}
?

main.php:
?php
namespace foo;
$a = new XMLReader; // loads ::XMLReader
include 'sneakyreader.php';
$a = new XMLReader; // still loads ::XMLReader
?

Whereas with the current behavior, it would instead instantiate
foo::XMLReader on the second access.  However, this is definitely a wtf
situation - the exact same looking line of code would load a different
class name entirely depending on what was included.

The cache does not eliminate the first autoload per-file.

I'm sure there are other issues to work out, but this should give a
better idea of what I am trying to do.

As for your question of whether to simply error out if foo::XMLReader
doesn't exist (in the main.php example above), this also would be
acceptable for classes, but not for functions, as the ratio of
user-defined to internal functions in any source code example is 1:many,
many.  However, we don't autoload functions or constants, so load ordr
is an absolute, much as it was for classes in PHP 4 before autoload was
introduced.

It is not an easy problem to solve, but we do need to solve it prior to
the next release.  Should we take this back on-list?

Greg


-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: Scoping of use statements and a strategy for 5.3/6.0 release of namespace

2008-09-11 Thread Gregory Beaver
Hi Stan,

I realized I missed 2 of your points, response below:

Stan Vassilev | FM wrote:
 Hi,
 
 Multiple namespaces per file were introduced to allow certain
 workflows in PEAR and frameworks like Symphony which can combine
 multiple classes and namespaces in a single package.
 
 They work like this:
 
 
 namespace X;
 
 ...
 
 namespace Y;
 
 ...
 
 
 The problem is, no one thought of scoping use statements, so now
 those merged files share their use imports, thus breaking all the
 code where collisions occur.
 
 Also we have the problems with name resolution of internal vs user
 classes and autoloaders, discussed here.

I just posted a patch that solves this problem, and a few minutes ago
forwarded two messages that further clarify how the patch works and why
it is a good solution to the problem.

 And we also have the non-intuitive differentiation between resolving
 functions/classes/constant which will most likely lead people to
 believe functions/constants aren't supported in any way in namespaces
 (if they try, and it doesn't work, they won't try second time).

The other 2 patches I have posted solve these issues decisively.

Since these would change namespace edge cases and introduce a new way to
import, I think an alpha3 is warranted.

The name resolution changes should not affect any existing working code
that utilizes namespaces, but should make it possible to do autoload
without having to use every single namespace class.

The patches do need review, and I am certain the patch introducing
function::blah::here() could be better written, and needs a Sara/Dmitry
type to take a quick look and say what could be done to improve it.

However, I don't think these facts warrant removal of the key feature of
namespaces, especially since they are relatively easy to solve - these
patches did not take many hours to whip up, and do not change very much.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: namespace RFC

2008-08-31 Thread Gregory Beaver
Lukas Kahwe Smith wrote:
 Hello all,
 
 All the recent discussions about namespaces, have left many of us
 wondering if our implementation is rock solid or not. However the
 discussions were not really well organized. This is why I am thankful
 that Marcus and Felipe have spend the better part of this Sunday to
 write an RFC [1] that hopefully summarizes all the key concerns. Also
 they have created a patch that they feel addresses the concerns.
 
 So I ask you all to review the RFC and provide feedback. If you feel
 something is missing, the best approach is probably to work with Marcus
 and Felipe directly to get your concerns added. Only if there is a
 difference of opinion in this process should this be brought to
 internals. This way we can hopefully keep the discussion more focused on

Hi,

This is not a difference of opinion, but I would like to correct a
misconception:  phar does *not* solve the problem that prompts
developers to concatenate files.

The problem is that the loading/unloading of the scanner and parser can
be significant overhead, and by cramming all code into a single file,
can result in a 10%-30% performance improvement over code in separate
files, even with an opcode cache.  This has been verified independently
by Zend labs (Stanislav can attest to this) on their machines.  The
performance difference depends on whether external code is loaded using
require with absolute path, require_once with relative path, autoload,
or some mix of these.

The problem requires streamlining of the loading process for files, and
could perhaps be addressed by attacking the bottleneck, but is not a
trivial problem to solve.

Just wanted to set the record straight.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Inconsistencies in 5.3

2008-08-13 Thread Gregory Beaver
Lukas Kahwe Smith wrote:
 
 On 13.08.2008, at 22:18, Stanislav Malyshev wrote:
 
 Simply include a script from two locations with different namespaces
 or one

 with namespace and the otherone without.

 I'm afraid you misunderstand how namespaces work. As I explained
 numerous times, namespaces are file-local, and this when including
 file, it does not matter a bit what was including context.
 
 I think Marcus is talking about files that are included that do not
 specify a namespace explicitly. In this situation the context does matter.
 
 We do not know if the developer in question is aware that the context
 would matter in this case. Actually like I said in a previous email it
 would be nice to at least not throw a warning if the file that is
 included specifies an explicit namespace (I assume that is possible?).
 Maybe adding a new include is a solution. This way developers can say
 explicitly what they want to do without having to suppress the warning.
 Then again quickly some smartass developer is going to teach people that
 these annoying warnings go away if you just use this new include
 everywhere. Then again, I am not sure if I even have my head wrapped
 around this entire namespace thing.

Hi,

Currently, if you include a file within a class method that contains
function definitions, they remain functions outside the class.  If you
include a file that contains a class.

In short, only global cpde is executed in the scope, and there is no
precedent in PHP to redefine re-usable elements based on scope.

Why would namespaces be any different?  This whole argument makes no
sense to me.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] enabling everything by default

2008-08-12 Thread Gregory Beaver
Antony Dovgal wrote:
 On 01.08.2008 14:11, Antony Dovgal wrote:
 I can agree that disabling something that was already enabled in 5.2
 might create some confusion, but why enable scarcely created
 extensions by default, especially if they are known to cause lost of
 obscure problems in the past (like Phar)?
 
 See http://bugs.php.net/bug.php?id=45613 for example.
 Who would have thought that there are multithreaded web-servers, eh?
 
 I'm going to disable ext/phar before alpha2.
 You've been warned.

Hi,

I've just returned home finally, and look forward to taking a look at
issues.  I even committed 2 new code coverage tests while on the road,
in case you doubt my resolve to fix things up.

Tony, please drop the posturing, it makes you look somewhat ridiculous
:).  I *explicitly* asked that the question of enabling phar by default
be voted on prior to rc 1 when I enabled it, and again reminded about it
a month later.  Please see the links below to the emails in question.

Let's not forget - disabling ext/phar by default involves changing a 1
to a 0 in config.m4, it's hardly difficult to do.  I agree that it needs
to happen prior to the final release cycle or not at all.  Is alpha2 the
new rc1?  That makes no sense to me if so.

Thanks,
Greg

From May 14, 2008: http://marc.info/?l=php-internalsm=121078127525090w=2
From June 23, 2008: http://marc.info/?l=php-internalsm=121419199122615w=2

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: simple solution to another namespace conundrum?

2008-06-21 Thread Gregory Beaver
Jessie Hernandez wrote:
 Hi Greg,

 How is this different from my original proposal
 (http://news.php.net/php.internals/34097,
 http://news.php.net/php.internals/34097)?



The patch committed only affects non-namespaced code, your proposal
affected all code.  In other words, this always works:

?php
namespace Foo;
include 'blah.php';
use Blah::Closure;
$a = new Closure();
?

whereas this:

?php
include 'blah.php';
use Blah::Closure;
$a = new Closure();
?

had the potential to fail with fatal error without code change on
upgrade to a newer PHP version that creates the Closure class.  The
committed patch addresses only this shortcoming, and changes nothing else.

In other words, this:

?php
namespace Foo;
$a = new Exception('hi');
var_dump(get_class($a));
?

still prints Exception and not Foo::Exception.

Additionally, unlike your proposal, all existing namespace tests still
pass with the behavior change.  2 new tests were added, 1 to test the
relaxed behavior, and 1 to test that this next example is a fatal error
because definition of Foo::Closure is in the same file as the use
Blah::Closure:

?php
namespace Foo;
include 'blah.php';
class Closure{}
use Blah::Closure; // unqualified name Closure is already taken, fatal
error.
?

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] interesting update on phar performance

2008-06-20 Thread Gregory Beaver
Hi all,

I decided to run my standard phpMyAdmin test without APC enabled and got
startling results from siege:

 Date  Time,  Trans,  Elap Time,  Data Trans,  Resp Time,  Trans
Rate,  Throughput,  Concurrent,OKAY,   Failed
2008-06-20 02:02:35,915,  60.01,   1,   0.98,  
15.25,0.02,   14.88, 915,   0 -- phpMyAdmin on disk
2008-06-20 02:05:04,911,  60.04,   1,   0.98,  
15.17,0.02,   14.86, 911,   0 -- phpMyAdmin in phar
with phar.cache_list

That's right - they are identical in performance.  With APC, there is a
performance difference (I'm not sure why, to be honest, this one is
really hard to profile):

 Date  Time,  Trans,  Elap Time,  Data Trans,  Resp Time,  Trans
Rate,  Throughput,  Concurrent,OKAY,   Failed
2008-06-20 01:34:00,   2735,  59.72,   5,   0.33,  
45.80,0.08,   14.95,2735,   0 -- phpMyAdmin on disk
2008-06-20 01:36:11,   2409,  60.14,   5,   0.37,  
40.06,0.08,   14.95,2409,   0 -- phpMyAdmin in phar
with phar.cache_list

However, the difference is negligible.  Thanks to Gopal for the
mini-tutorial on using copy-on-write to implement phar.cache_list, and
kcachegrind for finding the obvious bottlenecks.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] simple solution to another namespace conundrum?

2008-06-20 Thread Gregory Beaver
Hi,

You probably have seen Derick's blog post
http://www.derickrethans.nl/namespaces_in_php.php

It occurred to me today that there might be a simple, elegant solution
to this problem.

First, let's imagine someone writes this code:

?php
include '/path/to/library/Closure.php';
use Fancy::Closure;

$a = new Closure('for ($a = 1;$a10;$a++) docrap();');
?

Now, in PHP 5.4, we introduce an internal class Closure and the user's
code suddenly breaks on the use statement because we check for an
internal name conflict.

Here's the kicker: why do we need to worry about a name conflict?  This
user's code was designed to work exclusively with Fancy::Closure, and
doesn't care about any present or future internal classes that
conflict!  Also, because this is a compile-time alias that only affects
the current script file, if we were to allow the above user's code to
essentially override the internal Closure class, there is no possible
harm because

1) the user explicitly imported Fancy::Closure
2) the user therefore never intends to use the internal ::Closure in
this script

In fact, the same thing is true for existing classnames.  Why should we
care if a user does this?

?php
include '/path/to/my/date/lib.php';
use My::DateTime;

$a = new DateTime('2006/04/05');
?

The user is obviously intentionally creating a DateTime class, and
doesn't care about the internal classname in this script.

The attached patch against PHP_5_3 would fix the issue by eliminating
the check for conflict with CG(class_table) in the global namespace for
internal classes.  It however preserves this check for userspace classes
so that (for instance) php-src/tests/Zend/ns_030.phpt does not fail. 
The basic idea is that we do have control over the userspace classes we
include, but have no control over the internal classes.

A new test would also be needed:

066.php.inc:
?php
namespace A;
class B
{
function __construct(){echo __CLASS__;}
}
?

--TEST--
066: Name ambiguity (import name  internal class name)
--FILE--
?php
include __DIR__ . '/066.php.inc';
use A::B as stdClass;

new stdClass();
--EXPECT--
A::B

Thanks,
Greg
Index: Zend/zend_compile.c
===
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.647.2.27.2.41.2.68
diff -u -r1.647.2.27.2.41.2.68 zend_compile.c
--- Zend/zend_compile.c 15 Jun 2008 18:27:37 -  1.647.2.27.2.41.2.68
+++ Zend/zend_compile.c 20 Jun 2008 15:47:41 -
@@ -4959,6 +4959,7 @@
char *lcname;
zval *name, *ns, tmp;
zend_bool warn = 0;
+   zend_class_entry **pce;
 
if (!CG(current_import)) {
CG(current_import) = emalloc(sizeof(HashTable));
@@ -5012,14 +5013,16 @@
efree(tmp);
}
efree(ns_name);
-   } else if (zend_hash_exists(CG(class_table), lcname, 
Z_STRLEN_P(name)+1)) {
-   char *tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), 
Z_STRLEN_P(ns));
-
-   if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
-   memcmp(tmp, lcname, Z_STRLEN_P(ns))) {
-   zend_error(E_COMPILE_ERROR, Cannot use %s as %s 
because the name is already in use, Z_STRVAL_P(ns), Z_STRVAL_P(name));
+   } else if (SUCCESS == zend_hash_find(CG(class_table), lcname, 
Z_STRLEN_P(name)+1, (void **)pce)) {
+   if (pce[0]-type == ZEND_USER_CLASS) {
+   char *tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), 
Z_STRLEN_P(ns));
+   
+   if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
+   memcmp(tmp, lcname, Z_STRLEN_P(ns))) {
+   zend_error(E_COMPILE_ERROR, Cannot use %s as 
%s because the name is already in use, Z_STRVAL_P(ns), Z_STRVAL_P(name));
+   }
+   efree(tmp);
}
-   efree(tmp);
}
 
if (zend_hash_add(CG(current_import), lcname, Z_STRLEN_P(name)+1, ns, 
sizeof(zval*), NULL) != SUCCESS) {

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP-DEV] Re: simple solution to another namespace conundrum?

2008-06-20 Thread Gregory Beaver
Dmitry Stogov wrote:
 Looks fine, but probably we should emit error only if class declared in
 the same source file.

 Thanks. Dmitry.
   

Great, didn't realize how easy this would be.  Attached patch does this,
but requires another test:

067.php.inc:
?php
class B
{
function __construct(){echo __CLASS__;}
}
?

--TEST--
067: Name ambiguity (import name  userspace class name in another file)
--FILE--
?php
include __DIR__ . '/066.php.inc';
include __DIR__ . '/067.php.inc';
use A::B;

new B();
--EXPECT--
A::B


I can't express how excited I am about this patch - it fixes the biggest
single problem with the use statement and negates the need for any
weird stuff like namespace __user__; as proposed.  Now, once we fix
resolution rules, namespaces will be stellar.

Greg
Index: Zend/zend_compile.c
===
RCS file: /repository/ZendEngine2/zend_compile.c,v
retrieving revision 1.647.2.27.2.41.2.68
diff -u -r1.647.2.27.2.41.2.68 zend_compile.c
--- Zend/zend_compile.c 15 Jun 2008 18:27:37 -  1.647.2.27.2.41.2.68
+++ Zend/zend_compile.c 20 Jun 2008 16:37:53 -
@@ -4959,6 +4959,7 @@
char *lcname;
zval *name, *ns, tmp;
zend_bool warn = 0;
+   zend_class_entry **pce;
 
if (!CG(current_import)) {
CG(current_import) = emalloc(sizeof(HashTable));
@@ -5012,14 +5013,16 @@
efree(tmp);
}
efree(ns_name);
-   } else if (zend_hash_exists(CG(class_table), lcname, 
Z_STRLEN_P(name)+1)) {
-   char *tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), 
Z_STRLEN_P(ns));
-
-   if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
-   memcmp(tmp, lcname, Z_STRLEN_P(ns))) {
-   zend_error(E_COMPILE_ERROR, Cannot use %s as %s 
because the name is already in use, Z_STRVAL_P(ns), Z_STRVAL_P(name));
+   } else if (SUCCESS == zend_hash_find(CG(class_table), lcname, 
Z_STRLEN_P(name)+1, (void **)pce)) {
+   if (pce[0]-type == ZEND_USER_CLASS  
!strcmp(pce[0]-filename, CG(compiled_filename))) {
+   char *tmp = zend_str_tolower_dup(Z_STRVAL_P(ns), 
Z_STRLEN_P(ns));
+   
+   if (Z_STRLEN_P(ns) != Z_STRLEN_P(name) ||
+   memcmp(tmp, lcname, Z_STRLEN_P(ns))) {
+   zend_error(E_COMPILE_ERROR, Cannot use %s as 
%s because the name is already in use, Z_STRVAL_P(ns), Z_STRVAL_P(name));
+   }
+   efree(tmp);
}
-   efree(tmp);
}
 
if (zend_hash_add(CG(current_import), lcname, Z_STRLEN_P(name)+1, ns, 
sizeof(zval*), NULL) != SUCCESS) {

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP-DEV] heads up: new people in power at PEAR

2008-06-16 Thread Gregory Beaver
Hi,

For the past year, I have been representing PEAR as its president, but
decided not to seek re-election in order to pursue more heavily
development on phar and pyrus.  As of today, we finished our second set
of elections, and I'm happy to announce that David Coallier will be
taking my place as president, so if there are issues that affect PHP
core that involve PEAR, you should contact David, and if decisions in
the PHP core affect PEAR, expect to hear from David :).  The role of
president in the PEAR organization is more of an ambassadorial than
dictatorial role, and the president is the primary spokesperson and
spiritual leader of the organization.  Also elected was a combination
of new and old members for the PEAR Group, but that group is strictly
empowered to decide things internal to PEAR, so you all probably don't
care much :).

He can be reached through the email alias [EMAIL PROTECTED] (as
soon as the alias is updated) or through [EMAIL PROTECTED] (which will
also go to all of the newly elected PEAR group members).

For those interested, here are the official results:
http://pear.php.net/election/

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: FastArray, great addition

2008-06-16 Thread Gregory Beaver
Pierre Joye wrote:
 hi all,
 
 As you noticed already PHP finally got simple C-like array, thanks to
 Etienne and Tony for their great work!
 
 My only wish is to actually respect the informal decision we took a
 while back, to do not use fast, improved, better or similar
 wording in function or extension names. What's about naming it CArray
 or something similar? To reflect what it is, it is not a fast(er) hash
 table like our current array, it is a C-like array.

Why not call it SplVector?

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] potential shutdown order issue

2008-06-15 Thread Gregory Beaver
Hi,

I'm getting errors of hashtable already destroyed when running
phpMyAdmin with PHP 5.3, and (of course), thinking this is a phar issue,
I've traced through and found a problem in the shutdown order. 
Basically, php_request_shutdown() calls zend_deactivate() which calls
zend_destroy_rsrc_list(EG(regular_list)).  On the next line,
zend_post_deactivate_modules() is called, which steps through the module
list and unloads all the dynamically loaded modules.  If one of these
modules (like mysqli) declares a resource type, then in
module_destructor() zend_clean_module_rsrc_dtors() is called, which
calls zend_clean_modules_rsrc_dtors_cb() (zend_list.c:253).

This function then walks over EG(regular_list), which had been
previously destroyed.

I think this issue could be fixed by moving the
zend_destroy_rsrc_list(EG(regular_list)) call after the module
shutdown.  I've attached a patch demonstrating the principle (this fixes
the hashtable destroyed message and I don't get anything bad like a
segfault).

Could someone with more brains double-check this one?  I think it can be
reproduced with a debug build using mysqli loaded dynamically and any
script that uses mysqli, but I've only reproduced it with phpMyAdmin.

Thanks,
Greg
Index: Zend/zend.c
===
RCS file: /repository/ZendEngine2/zend.c,v
retrieving revision 1.308.2.12.2.35.2.18
diff -u -r1.308.2.12.2.35.2.18 zend.c
--- Zend/zend.c 29 Apr 2008 08:15:16 -  1.308.2.12.2.35.2.18
+++ Zend/zend.c 16 Jun 2008 02:53:00 -
@@ -901,7 +901,8 @@
shutdown_compiler(TSRMLS_C);
} zend_end_try();
 
-   zend_destroy_rsrc_list(EG(regular_list) TSRMLS_CC);
+   /* shutdown order issue */
+   /* zend_destroy_rsrc_list(EG(regular_list) TSRMLS_CC); */
 
 #ifdef ZEND_DEBUG
if (GC_G(gc_enabled)  !CG(unclean_shutdown)) {
Index: main/main.c
===
RCS file: /repository/php-src/main/main.c,v
retrieving revision 1.640.2.23.2.57.2.22
diff -u -r1.640.2.23.2.57.2.22 main.c
--- main/main.c 21 May 2008 15:55:31 -  1.640.2.23.2.57.2.22
+++ main/main.c 16 Jun 2008 02:53:02 -
@@ -1527,6 +1527,8 @@
zend_post_deactivate_modules(TSRMLS_C);
} zend_end_try();
 
+   zend_destroy_rsrc_list(EG(regular_list) TSRMLS_CC);
+
/* 9. SAPI related shutdown (free stuff) */
zend_try {
sapi_deactivate(TSRMLS_C);

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP-DEV] phar development update

2008-06-13 Thread Gregory Beaver
Hi all,

A quick note on significant improvements to phar committed recently:

 * tar-based archives now fully support metadata and signatures,
bringing them in line with more of the features of phar-based phar archives.
 * true asymmetric signing support using OpenSSL private/public key pairs
 * phar.cache_list provides pre-parsing of phar manifests at MINIT, with
performance enhancement that matches on-disk for non-APC and improves
perf to 19 req/sec (in-phar) vs. 28 req/sec (on-disk) in my benching of
phpMyAdmin with APC.  This performance benefit only accrues with
webservers that run MINIT once and then spawn other processes/threads
with RINIT.

Also, Scott is working on a patch to sqlite that will allow using
databases mounted inside a phar archive with a phar url, which will
greatly simplify pharring apps that use sqlite.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] missing pestrndup

2008-06-12 Thread Gregory Beaver
Hi,

Is there any reason pestrndup is missing from PHP 5.3's zend_alloc.h but
is present in HEAD?

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] [PATCH] add pestrndup

2008-06-12 Thread Gregory Beaver
Hi,

I need this patch committed ASAP to PHP_5_3 zend_alloc.h, as the commit
I just made for ext/phar depends on it (oops).  Could someone help me out?

Thanks :),
Greg
Index: zend_alloc.h
===
RCS file: /repository/ZendEngine2/zend_alloc.h,v
retrieving revision 1.63.2.2.2.12.2.4
diff -u -r1.63.2.2.2.12.2.4 zend_alloc.h
--- zend_alloc.h31 Dec 2007 07:17:04 -  1.63.2.2.2.12.2.4
+++ zend_alloc.h13 Jun 2008 03:59:30 -
@@ -113,6 +113,7 @@
 #define safe_perealloc(ptr, nmemb, size, offset, persistent)   
((persistent)?_safe_realloc((ptr), (nmemb), (size), 
(offset)):safe_erealloc((ptr), (nmemb), (size), (offset)))
 #define perealloc_recoverable(ptr, size, persistent) 
((persistent)?__zend_realloc((ptr), (size)):erealloc_recoverable((ptr), (size)))
 #define pestrdup(s, persistent) ((persistent)?strdup(s):estrdup(s))
+#define pestrndup(s, length, persistent) 
((persistent)?zend_strndup((s),(length)):estrndup((s),(length)))
 
 #define pemalloc_rel(size, persistent) 
((persistent)?__zend_malloc(size):emalloc_rel(size))
 #define pefree_rel(ptr, persistent)((persistent)?free(ptr):efree_rel(ptr))

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP-DEV] Re: cvs: ZendEngine2(PHP_5_3) / zend_alloc.h

2008-06-12 Thread Gregory Beaver
Matt Wilmas wrote:
 mattwil   Fri Jun 13 04:16:59 2008 UTC
 
   Modified files:  (Branch: PHP_5_3)
 /ZendEngine2  zend_alloc.h 
   Log:
   MFH: Add pestrndup()

Thanks Matt

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] CVS Account Request: baptiste750

2008-06-11 Thread Gregory Beaver
Hannes Magnusson wrote:
 On Wed, Jun 11, 2008 at 22:15, Rasmus Lerdorf [EMAIL PROTECTED] wrote:
 Actually, checking through my group@ archive, I don't see 2 messages from
 you.  The only one I see from you is one from June 9 complaining that your
 cvs account wasn't granted.  I see that someone has approved your account
 now.
 
 Sorry, my fault. I silently forwarded the mail to pear-group@ and his
 account was approved few minutes later.
 
 I have a patch adding a combobox to pick which group the request
 should be sent to (pear/php, and maybe add gtk/pecl/doc/... in the
 future?), so the pear guys don't have to subscribe to this list or
 manually search for outstanding requests, which I'll commit in few
 minutes...

Hi,

Sorry about this, I dropped the ball here.

As a note, I have been approving PEAR account requests, and simply
monitored internals@ for emails.  This worked great until the past
couple of weeks when I had crappy internet while on the road, so I
missed a few (3 to be exact).

This is not the responsibility of people outside PEAR like Rasmus, and
the solution is actually a technical one (being able to filter
unapproved accounts by project at master.php.net, i.e. PEAR requests
only are shown), along with the patch Hannes has already committed.
This way, when I am away, it is also possible for people outside PEAR to
easily filter the requests, and I can also do that when I come back
quite easily.

No worries folks - the average turnaround for account approval has been
under 24 hours for over a year now, down from an average of 1 month, so
this 1 week aberration is a 1-time occurrence.  In addition, when PEAR2
gets rolling (and it already is starting) we use a separate subversion
repo with its own auth system, which will help as the volume of cvs
account requests should decline.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: Calling original function from an overloaded function

2008-06-09 Thread Gregory Beaver
Christoph Dorn wrote:
 I have been looking at xdebug and have figured out how to overload a
 function. As a test I have overloaded the var_dump function.
 
 Now how do I call the original var_dump function from my implementation?
 Borrowing from OO terminology I have subclassed the var_dump method, now
 I want to call parent::var_dump() from my subclass.
 
 Also how does overloading work when two extensions overload the same
 function? Can this be done? Is there some sort of order? Can I let the
 other extension overload the function and then overload the function
 from the other extension?
 
 Any pointers would be greatly appreciated.

Hi,

phar does exactly what you're describing, this is all encapsulated in
func_interceptors.c:

http://cvs.php.net/viewvc.cgi/php-src/ext/phar/func_interceptors.c?revision=1.20.2.1content-type=text%2Fplainpathrev=1.20.2.1

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [PATCH] fix building openssl shared on unix in 5.3

2008-06-01 Thread Gregory Beaver
Pierre Joye wrote:
 hi Greg,

 Please commit it, thanks for the patch!

   
Someone with ZendEngine2 karma will need to commit.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] [PATCH] fix building openssl shared on unix in 5.3

2008-05-31 Thread Gregory Beaver
Hi,

I was trying to test building openssl shared, and ran into an unexported
symbol issue because the arginfo constant arrays are never exported for
dll/so use.  Could someone check out this patch and make sure it doesn't
fubar windows in particular?  The same patch will apply in all branches
just fine.

Thanks,
Greg
Index: Zend/zend_arg_defs.c
===
RCS file: /repository/ZendEngine2/zend_arg_defs.c,v
retrieving revision 1.2.2.2.2.2.2.1
diff -u -r1.2.2.2.2.2.2.1 zend_arg_defs.c
--- Zend/zend_arg_defs.c31 Dec 2007 07:17:04 -  1.2.2.2.2.2.2.1
+++ Zend/zend_arg_defs.c1 Jun 2008 03:26:00 -
@@ -18,29 +18,29 @@
 
 /* $Id: zend_arg_defs.c,v 1.2.2.2.2.2.2.1 2007/12/31 07:17:04 sebastian Exp $ 
*/
 
-ZEND_BEGIN_ARG_INFO(first_arg_force_ref, 0)
+ZEND_API ZEND_BEGIN_ARG_INFO(first_arg_force_ref, 0)
ZEND_ARG_PASS_INFO(1)
 ZEND_END_ARG_INFO();
 
-ZEND_BEGIN_ARG_INFO(second_arg_force_ref, 0)
+ZEND_API ZEND_BEGIN_ARG_INFO(second_arg_force_ref, 0)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
 ZEND_END_ARG_INFO();
 
-ZEND_BEGIN_ARG_INFO(third_arg_force_ref, 0)
+ZEND_API ZEND_BEGIN_ARG_INFO(third_arg_force_ref, 0)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
 ZEND_END_ARG_INFO();
 
-ZEND_BEGIN_ARG_INFO(fourth_arg_force_ref, 0)
+ZEND_API ZEND_BEGIN_ARG_INFO(fourth_arg_force_ref, 0)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(1)
 ZEND_END_ARG_INFO();
 
-ZEND_BEGIN_ARG_INFO(fifth_arg_force_ref, 0)
+ZEND_API ZEND_BEGIN_ARG_INFO(fifth_arg_force_ref, 0)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(0)
ZEND_ARG_PASS_INFO(0)
@@ -48,5 +48,5 @@
ZEND_ARG_PASS_INFO(1)
 ZEND_END_ARG_INFO();
 
-ZEND_BEGIN_ARG_INFO(all_args_by_ref, 1)
+ZEND_API ZEND_BEGIN_ARG_INFO(all_args_by_ref, 1)
 ZEND_END_ARG_INFO();

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP-DEV] Re: Short syntax for array literals [...]

2008-05-28 Thread Gregory Beaver
I've thought about allowing [] for a while and personally have come up
with my own litmus test for new features.

1) is the syntax missing from the language?
2) if so, does the syntax add missing functionality or significant
maintenance benefit?
2) if not, does the new syntax add significant value?

#1 no, array() is the same [-1]
#2 not applicable [0]
#3 [-.5]
 * can't google []
 * makes arrays simpler to type and take up less space
 * adds potential for confusion between array access and creation:

$a['hi'];
$a;['hi'];

both are now suddenly valid PHP

 * syncs with javascript and other languages
 * opens pandoras box - PHP is simpler than Perl because there are not
20 ways of doing the same thing with different punctuation shorthands

So I find #1 is -1, #2 is 0, #3 is about -.5

Although the idea is somewhat attractive, I've found no drawbacks to
array() syntax, and plenty of dangers with adding any new alternate
syntax, and this ultimately makes my vote -1

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] magic quotes finale

2008-05-23 Thread Gregory Beaver
Rasmus Lerdorf wrote:
 I see absolutely no reason to force people to go through and change:
 
 if(!get_magic_quotes_gpc())
 
 to:
 
 if (!function_exists('get_magic_quotes_gpc') || !get_magic_quotes_gpc())
 
 when there is no technical reason to force them to do so.  It is slower,
 more verbose and completely useless.

I whole-heartedly agree.

To the others: please examine this from a practical instead of a
philosophical position.

What is the problem that needs solving?

 * magic_quotes_gpc escapes input, which is bad.

How to fix it?

 * disable magic_quotes_gpc = on, disable set_magic_quotes_gpc(1)

Implicit in this statement is that the problem is *not*:

 * Users use get_magic_quotes_gpc() check whether this faulty ini is
enabled, and set_magic_quotes_gpc(off) only if it is enabled.

If we take the step of removing the get_magic_quotes_gpc() function, or
of adding an E_DEPRECATED, we make upgrading to PHP 5.3 harder, for no
benefit.

As a side note, the silent majority (developers who do not post to this
list) were represented at php|tek, and the few I spoke to about the way
magic_quotes is being handled unequivocally agreed with my assessment
for the exact same reasons.

I strongly encourage everyone to do a realistic tradeoff analysis and
come to understand why Rasmus's solution is the only possible solution
to this problem that both solves the *actual* problem and has real
benefit to existing well-written applications.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] HEADS UP: phar now enabled statically by default

2008-05-17 Thread Gregory Beaver
Hi,

I've reversed my initial patch enabling phar as shared by default, and
instead now enable it statically by default.

I was able to solve the dependency on zlib/bz2 I noted in my last
message through some very simple logic, and testing confirms that phar
can be built statically with zlib/bz2 shared with absolutely no problems
whatsoever because phar never uses these extensions directly, only
through the stream filter API.

So, in short, problem solved, and phar can be built statically and works
just great with static zlib/bz2 or shared zlib/bz2.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: Please help about zend engine

2008-05-16 Thread Gregory Beaver
Andreas K Santoso wrote:
 Hello sir/ma'am
 
 My name is andre from Indonesia. I am a student of a university, and
 i'm doing my thesis. I subscribe to this list to look for some help. 
 Oh by the way, my thesis is about PHP file encryption. So i need to
 decrypt the file when it's accessed and before any further
 processing. I'm surely not as smart and experienced as all of you, so
 please be patient
 
 Mr. Malyshev told me that i have 2 options 1. Override the
 zend_compile function (he said that this one seems to be the easiest
 way) 2. Use the PHP stream system (http://php.net/streams) to create
 filters that decrypt data on-the-fly.
 
 So i decided to try the second option. But still i can't understand
 it well. The example  i've read (http://php.net/streams) is not clear
 enough for me. I mean, how to make the filter itself, and how to use
 it? and can the filter automaticaly applied to every .php files?
 
 And can anyone tell me where i must insert my codes if i want to
 override the zend_compile? I'm afraid that i don't have much time
 left, so if i can't use option 2, i will use option 1 instead.
 
 
 Sorry if my english impolite or confusing. Thank you very much for
 your patience and help.

Hi Andreas,

For stream filters, check out the zlib and bz2 stream filters in
ext/zlib/zlib_filter.c and
ext/bz2/bz2_filter.c

The filter can't be automatically applied without overriding
zend_compile, but I still highly recommend you implement it as a stream
filter.  Why?  You can check for encryption on file inclusion and then
append the  stream filter to the returned stream inside the
zend_file_handle, or disable this in php.ini and decrypt on a per-file
basis manually.

For an example of zend_compile() interception that does something
similar, look at the end of ext/phar/phar.c.  In this case, phar's
zend_compile override checks for filenames containing '.phar' and
attempts to process them as a phar archive, creates a phar stream URL
and passes that to zend_stream_open_function to return a file_handle.
You could simply call zend_stream_open_function, and then read in the
first few bytes of the file handle in the modified zend_file_handle * to
determine if decryption is necessary, and then use code something like
this to append the filter and compile the file:

filter = php_stream_filter_create(my.encrypt, NULL,
php_stream_is_persistent(file_handle-handle.stream.handle) TSRMLS_CC);
php_stream_filter_append(file_handle-handle.stream.handle-readfilters,
encrypt_filter);
return encrypt_orig_compile_file(file_handle, type TSRMLS_CC);

where encrypt_orig_compile_file is the saved value of zend_compile_file.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: 5.3 Namespace resolution rules suggestions

2008-05-16 Thread Gregory Beaver
Nathan Rixham wrote:
 Ryan Panning wrote:
 Jessie Hernandez wrote:
   Hi Stan,
  
   I made a proposal and patch a few months ago...

 The developers should really take a serious look at this issue or it
 will come back to haunt them later. I'm not sure why no one seems
 comment on your proposal and patch. It seemed like a well thought-out
 and good proposal to me.

 I'm also wondering what happened to the namespace declaration change
 to brackets {}. I've downloaded the latest snap of 5.3 and that has
 not changed as of yet.
 
 is it too late to scrap all this and go with Java/AS3 style
 base.package.class please?

yes

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: 5.3 Namespace resolution rules suggestions

2008-05-16 Thread Gregory Beaver
Stan Vassilev | FM wrote:
 Hi,
 
 I'd like to nudge the discussion back to issues with the resolution
 rules that we're discovering :)
 The actual char(s) used can only be mildly annoying to some (at worst),
 compared.
 
 Can we please agree on those (or explain why you'd not):
 
 1) functions, constants and classes should use the same resolution
 rules. Making special cases just for some of them, or just for user or
 just internal ones will lead to confusion.

I have to agree.  In fact, there is a simple and elegant solution to the
problem that involves augmenting Jessie's patch to include a more
helpful error message on class/function not found, and a simple 51-line
PHP script for converting non-namespaced to namespaced code.  With these
two things, I think we could safely change the name resolution in PHP.

 2) can someone please explain why is it useful to override internal
 function inside a namespace. Isn't it better to explicitly refer to
 global functions as global, which would allow compile-time resolution in
 a lot more cases than now.

The reasoning behind this decision that I was given by Dmitry and
Stanislav was 2-fold.

1) Currently, the lookup order is optimized for internal
functions/classes [more detail below]
2) migrating existing code to namespaces will require much more work if
all internal functions/classes must be prefixed with :: or used to be
avialable

Detail:

1) Currently the lookup order is optimized for internal functions/classes.

At compile-time, all internal classes/functions exist.  However, it is
possible that not all userspace functions/classes exist yet.  As such,
if a T_STRING is encountered, here is how the resolution works currently
in the worst case (roughly, in pseudo-code):

= is it an internal function/class? if so, use it
= does it exist in the current namespace? if so use it
= otherwise, mark it for runtime resolution
= run code
= when we reach this opcode, resolve the function

In the best case:

= is it an internal function/class? use it

However, changing this to allow resolving always to the current
namespace would change this to:

worst case:
= does it exist in the current namespace? if so use it
= otherwise, mark it for runtime resolution
= run code
= when we reach this opcode, resolve the function

best case:
= does it exist in the current namespace? if so use it

This results in a fatal error for all internal functions/classes.  The
error message for a non-existing class/function should at least hint
that a use statement is needed, an element missing from Jessie's patch.

In any case, #1 proves to be false, as adding a use clause for each
internal function/class is no performance hit at all.

2) migrating existing code to namespaces will require more work if all
internal functions/classes must be prefixed with :: or used

As a test, I tried adding a namespace declaration to the top of one of
PEAR's larger file, and then ran it with PHP 5.3 and the patch.  To my
(initial) surprise, it ran without error.  On further investigation, I
realized why this is so - none of the internal functions/classes were
actually resolved, all of them were delayed until runtime, and none were
actually executed.

What this means is that by adding a namespace declaration, it is quite
possible that your code will execute happily until it suddenly
encounters a function/class you forgot to use or prefix with ::.

Fortunately, I just wrote a simple namespace conversion script that
solves this problem decisively.  The eventual script should be checked
over for missing userspace class/functions, as only internal
class/functions will be used.  Here it is:

?php
namespace NSParser;
class Parser
{
protected $tokens;
protected $i = -1;
protected $classes = array();
protected $functions = array();
protected $use = array();
protected $ret;

function __construct($path, $namespace)
{
$classes = ::get_declared_classes();
$classes = ::array_merge($classes, ::get_declared_interfaces());
$this-classes = ::array_flip($classes);
unset($this-classes['NSParser::Parser']);
$functions = ::get_defined_functions();
$this-functions = ::array_flip($functions['internal']);
if (@::is_file($path)) {
$path = ::file_get_contents($path);
}
$this-tokens = ::token_get_all($path);
foreach ($this-tokens as $token) {
if (!::is_array($token)) {
$token = array(::ord($token), $token);
}
}
$ret = ?php\nnamespace  . $namespace . ;\n;
do {
if ($this-tokens[$this-i][0] == T_STRING) {
if (isset($this-classes[$this-tokens[$this-i][1]])) {
$this-use[$this-tokens[$this-i][1]] = 1;
}
if (isset($this-functions[$this-tokens[$this-i][1]])) {
$this-use[$this-tokens[$this-i][1]] = 1;
}
}
} while (++$this-i  

Re: [PHP-DEV] Re: 5.3 Namespace resolution rules suggestions

2008-05-16 Thread Gregory Beaver
Stanislav Malyshev wrote:
 Hi!

 $classes = ::get_declared_classes();
 $classes = ::array_merge($classes, ::get_declared_interfaces());
 $this-classes = ::array_flip($classes);
 unset($this-classes['NSParser::Parser']);
 $functions = ::get_defined_functions();
 $this-functions = ::array_flip($functions['internal']);
 if (@::is_file($path)) {
 $path = ::file_get_contents($path);

 Do you really think that's how PHP code should look like - constant
 obsessive ::-ing? For my taste, it looks very bad.
Actually, no.  The irony of your message is that the code you quote is
used to generate use statements so ::this ::is ::unnecessary.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] phar enabled by default as of now

2008-05-15 Thread Gregory Beaver
Hi,

I just committed to ext/phar's config.m4/w32 to make phar enabled by
default as a shared extension.  This is a better default setting than
building phar in statically, as phar has optional dependencies on the
zlib and bz2 extensions to enable compressed phar archives.  If phar is
built statically, then it would require both zlib and bz2 to be built
statically in order to use them, something that is obviously not going
to happen, as they have been around a while and nobody has even
suggested it (to my knowledge).  Having phar shared means one can easily
plug in zlib/bz2 support without recompiling PHP.

I'm open to further input/tweaks on this decision.  If you have a better
idea, go ahead and commit to phar's config.m4/w32, these files are very
easy to change if needed.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] [HEADS UP] pecl/phar is now ext/phar

2008-05-14 Thread Gregory Beaver
Richard Quadling wrote:
 2008/5/13 Antony Dovgal [EMAIL PROTECTED]:
   
 On 13.05.2008 01:45, Gregory Beaver wrote:
 
 Thanks to all who have contributed, particularly Marcus, Steph, Lars,
 and the others who chimed in with ideas on the list.
   
 phar_detect_phar_fname_ext() fails if is_complete = 1 and filename contains
 ..

 For example:
 Breakpoint 1, phar_detect_phar_fname_ext (filename=0x124db80
 /local/qa/5_3.zts/ext/phar/tests/DataArchive.phar, check_length=1,
 


 Am I being picky in saying that having a . in a folder containing a
 file should be allowed? And if there is an extension on the filename,
 then it will also have a .
   
This was always the intention, and is already fixed.  In fact, opening
URLs like phar://whatever/has.dot/my.phar/internal/file.php already
worked, the only thing broken was instantiating a Phar object with a
path containing .
 What happens for relative filenames?

They have worked since phar 2.0.0a1.  The only requirement for phar to
detect its file is that you either use a registered alias or that the
filename contain a ..  Executable phar archives must also contain
.phar as part of the filename extension.

In short, the problem with Phar objects crept in only because none of us
had a path in our dev environment containing a . and didn't think to
add a test case for it until the problem appeared.  It's now fixed, and
all tests pass in CVS.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] objection to enabling phar for testing in 5.3?

2008-05-14 Thread Gregory Beaver
Hi,

I wonder if there is any objection to this plan:

1) enable phar by default for the PHP 5.3 betas, so that it can receive
full testing
2) before RC1, do the formal vote on whether it should be enabled by
default in the release

This way, phar can be tested for the possibility of enabling, but there
is an explicit safety net in place should it need reconsidering.

My assumption here is that there will be a few beta releases and
possibly an alpha release or two prior to the first RC.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] [HEADS UP] pecl/phar is now ext/phar

2008-05-12 Thread Gregory Beaver
Hi,

It's time for helly's birthday present from me (and indirectly, Derick,
who did the cp -r) :).

As Johannes requested, pecl/phar has been copied to php-src/ext/phar,
development will continue there.  I suspect there may need to be some
changes at gcov.php.net to keep things running smoothly, so this is a
heads up message.

At this point, phar is ready for the big question: enable by default or
not.  My benchmarking shows no detectable difference in speed between
ext/phar enabled and ext/phar disabled for regular applications, but I
would love some confirmation on this.

In addition, I just released phar 2.0.0b1 through pecl.  Full
documentation is available through http://php.net/phar of the latest
API.  Changes from the last update I sent to internals:

 * code coverage is pushing 80%, up from about 63%
 * small performance increases
 * many, many small and some large bugs fixed
 * compression/conversion API completely re-worked
 * lots of other improvements detailed in the manual
 * 373 regression/unit tests
 * filename requirements completely rewritten to allow processing things
like openoffice odt zip files
 * full API mirroring of ext/zip, so phar can be easily used by
developers used to this API
 * phar.extract_list removed as obsolete

I benchmarked phpMyAdmin in/out of phar, and got 17 req/sec with phar,
and 28 req/sec without phar using APC.  I also ran a compressed phar,
and got 6.62 req/sec, so compression is a significant performance hit.

There is obvious room for improvement of performance, and this is going
to be a major focus moving forward, as correctness is nearly complete
(there are still a few lines of code that are testable, mostly extreme
edge cases), and documentation is nearly complete.  Another area of
focus will be tutorials in the manual on how to create phars, usability
tips, and performance information for comparing the formats.

At this point, phar's API is slushy in the sense that I would like to
freeze it where it is unless we've completely missed the boat on
something.  I would like a full review from interested parties, and I'd
also like to openly call for security review of the code.  I have spent
a lot of time trying to think of bad guy stuff that could be done with
phar, and thus far have covered things like:

 * phar.readonly=1 (default) cannot be disabled except in system php.ini
(ini_set fails), and means that executable phar archives cannot be
modified by any PHP process.
 * aliases cannot contain any path separators or : or ;
 * tar/zip-based archives can't be magically made into phar archives
simply by renaming them, as they won't contain the executable stub
necessary to run them
 * open_basedir/safemode checks are in place every time an external path
is accessed - I particularly need checking of this constraint, as I am
relatively unfamiliar with either system.

I've also checked for every buffer overflow/invalid read that I could
find, using safe functions wherever possible, and carefully checking the
few uses of strcat and company.  Valgrind reports no leaks/problems
(except in libz, which is an external library used by zlib compression)
in 2.0.0b1.  In spite of my paranoia and exhaustive attempts to kill any
potential security issues, I don't claim to be any kind of security
expert, so any and all scrutiny of phar on this front is greatly
appreciated.

Thanks to all who have contributed, particularly Marcus, Steph, Lars,
and the others who chimed in with ideas on the list.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] php_stream_display_wrapper_errors issue

2008-04-14 Thread Gregory Beaver
Pierre Joye wrote:
 Hi Greg,

 On Mon, Apr 14, 2008 at 12:17 AM, Gregory Beaver [EMAIL PROTECTED] wrote:
   
 Hi,

  If a stream wrapper does not log errors, by default, we grab
  strerror(errno) to figure out the error message, but this is not a good
  idea for any wrapper but plain_wrapper for the obvious reason that errno
  is not used by wrappers that don't use sys calls.

  Is this patch against 5.3 acceptable (I'll merge to HEAD on commit if so)?
 

 I think it fixes the possible misguided error messages. To go one step
 further, I wonder if it would make sense to add a stream_strno and
 stream_strerror to _php_stream_wrapper_ops. It may be helpful to
 display the actual error or for debugging purposes (user land or
 internally). Comments?

Hi,

In theory, a stream wrapper should be using
php_stream_wrapper_log_error() for all errors, so I think
stream_strerror should be unnecessary.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] php_stream_display_wrapper_errors issue

2008-04-13 Thread Gregory Beaver
Hi,

If a stream wrapper does not log errors, by default, we grab
strerror(errno) to figure out the error message, but this is not a good
idea for any wrapper but plain_wrapper for the obvious reason that errno
is not used by wrappers that don't use sys calls.

Is this patch against 5.3 acceptable (I'll merge to HEAD on commit if so)?

Greg
Index: main/streams/streams.c
===
RCS file: /repository/php-src/main/streams/streams.c,v
retrieving revision 1.82.2.6.2.18.2.7
diff -u -r1.82.2.6.2.18.2.7 streams.c
--- main/streams/streams.c  27 Mar 2008 10:33:40 -  
1.82.2.6.2.18.2.7
+++ main/streams/streams.c  13 Apr 2008 20:41:23 -
@@ -164,7 +164,11 @@
 
free_msg = 1;
} else {
-   msg = strerror(errno);
+   if (wrapper == php_plain_files_wrapper) {
+   msg = strerror(errno);
+   } else {
+   msg = operation failed;
+   }
}
} else {
msg = no suitable wrapper could be found;

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

[PHP-DEV] phar API update

2008-04-11 Thread Gregory Beaver
Hi,

A quick update on Phar's API for those who are keeping score:

1) Phar-isWritable() now works properly and does what Liz was hoping:
tells you whether you can actually modify the phar archive by looking at
the archive's file perms as well as phar.readonly
2) PharFileInfo-getContent() added to retrieve file contents like
$phar['a.txt']-getContent()
3) addFile/addFromString/addEmptyDir added to match ext/zip API
4) fixed compression API.  Here are the new methods:

bool Phar-isCompressed([int compression]) // takes Phar::GZ, Phar::BZ2
or no parameter to check for any whole-archive compression
Phar|PharData Phar-compress(int compression[, string ext]) // takes
Phar::GZ/Phar::BZ2 and optional file extension to override default renaming
Phar|PharData Phar-decompress([, string ext]) // takes optional file
extension to override default renaming
bool Phar-compressFiles(int compression) // takes Phar::GZ/Phar::BZ2
and compressed all files within the archive
bool Phar-decompressFiles() // decompress all files within the archive
Phar Phar-convertToExecutable([int format[, int compression[, string
ext]]])
PharData Phar-convertToData([int format[, int compression[, string ext]]])
// takes Phar::TAR, Phar::ZIP, or Phar::PHAR as format
// takes Phar::GZ, Phar::BZ2 as compression
// optional file extension to override default renaming

PharFileInfo-isCompressed([int compression]) // takes Phar::GZ,
Phar::BZ2 or no parameter to check for any compression of file within
the archive
PharFileInfo-compress(int compression) // Phar::GZ/Phar::BZ2
PharFileInfo-decompress()

Here's code example of the new API:

?php
$phar = new Phar('blah.phar');
$tar = $phar-convertToData(Phar::TAR); // creates blah.tar
$tgz = $tar-compress(Phar::GZ); // creates blah.tar.gz
$phargz = $tar-convertToExecutable(Phar::PHAR, Phar::GZ, '.gz.phar');
// creates blah.gz.phar (default would be blah.phar.gz)

var_dump($tgz-isCompressed(), $tgz-isCompressed(Phar::GZ),
$tgz-isCompressed(Phar::BZ2)); // true, true, false

$phar['a.txt'] = 'hi';
echo $phar['a.txt']-getContent(); // hi

$phar-compressFiles(Phar::GZ); // internal files compressed with zlib
compression
var_dump($phar['a.txt']-isCompressed(),
$phar['a.txt']-isCompressed(Phar::GZ),
$phar['a.txt']-isCompressed(Phar::BZ2)); // true, true, false
$phar['a.txt']-decompress(); // now this specific file is not
compressed within the archive

$phar-decompressFiles(); // internal files decompressed
$phar['a.txt']-compress(Phar::BZ2); // now this specific file is
compressed with bzip2 compression

$tar2 = $tgz-decompress('.2.tar'); // creates blah.2.tar
$phartar2 = $tar2-convertToExecutable(); // create blah.2.phar.tar
?

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] spl documentation

2008-04-11 Thread Gregory Beaver
Philip Olson wrote:
 
 On 11/04/2008, Alexey Zakhlestin [EMAIL PROTECTED] wrote:
 I noticed, that
 http://www.php.net/~helly/php/ext/spl/http://www.php.net/%7Ehelly/php/ext/spl/was
 updated
 almost a year ago. Is the newer version available anywhere?


 Good point, there're so many new things in there. Marcus? Etienne?
 Anyone up to do regenerate some docs ?

 

 I've a more recent build that covers DLLists, but only Marcus is able to
 upload it to ~helly.

 I guess a new version will be online as soon as I finish documenting
 Heaps
 and priority queues.
 
 I think all effort should go into writing real documentation within the
 phpdoc cvs module instead of unreadable and unofficial doxygen output.
 Personally I feel the link to the doxygen output should be removed from
 php.net/spl (but won't) so anyway those are my feelings. Etienne is
 planning to work on both, which is great, but I encourage everyone to
 update the official spl documentation and not worry much about doxygen.

+1

This finally makes sense with the new doc style, which is OO-friendly.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] practical phar considerations

2008-04-09 Thread Gregory Beaver
Pierre Joye wrote:
 Hi,

 On Wed, Apr 9, 2008 at 6:48 AM, Gregory Beaver [EMAIL PROTECTED] wrote:

   
   For other examples, take a look at at
  ext/zip.  There is no support for opendir() in the stream wrapper of
  ext/zip because it requires the kind of path grepping that pecl/phar
  does.
 

 That's easy to add and will be available at some point, that was
 simply not needed and nobody ever requested this feature. Extract or
 add using a pattern is however much more useful. It is already
 partially supported.
Yes, I agree.
   Yes, this shouldn't be allowed while
   $phar['foo/bar/baz'] = new DirectoryIterator(); could be allowed.

  I will simply add makeEmptyDir() a la zip, although it is too bad
  ext/zip never thought to go with mkdir().
 

 I thought about mkdir but it is a bad name as it implies a shell
 command. makeEmptyDir while being longer is self explaining. I also
 asked before choosing this name, as far as I remember nobody proposed
 mkdir either.

I'm fine with makeEmptyDir(), I was just thinking out loud :)

This wasn't intended to be a referendum on ext/zip, just to be clear.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] practical phar considerations

2008-04-09 Thread Gregory Beaver
Steph Fox wrote:
 Hi Greg,
 
 What I would like to do, however, is to rethink offsetSet().  I think
 that we should introduce a property of PharFileInfo called content
 that is read/write, and can be used to perform the equivalent of
 file_get_contents()/file_put_contents().  This will allow a consistency
 that is much more intuitive.  offsetSet() could then simply be removed,
 or perhaps be refactored as a way to pass in a PharFileInfo and clone
 the information.
 
 Could you offer up some pseudo-code showing how this will be used? I
 can't visualize it at all from that description.

I should have done this in the original post, because it turns out that
it would require offsetGet() to implicitly create the file, which brings
me back to my original objection to these changes.  I'm adding in
getContents() right now to retrieve the file contents into a string, so
one can do:

?php
$phar = new Phar('blah.phar');
echo $phar['path/to/file.txt']-getContents();
?

The truth is, I think offsetSet() could accept either a string/fp (file
contents) or a PharFileInfo() that can be used to set a slew of things:

 - metadata
 - per-file compression
 - file contents

This would also be relatively trivial to implement.

 One problem with this suggestion is that phar renames the archive by
 default when compressing.  I would rather we combine compression and
 format conversion into a single convert() method that accepts constants.

 $phar = new Phar('blah.phar');
 $phar = $phar-convert(Phar::GZ); // compress with gzip
 $phar = $phar-convert(Phar::TAR | PHAR::GZ); // convert to .phar.tar.gz
 $phar = $phar-convert(Phar::NONE | PHAR::DATA); // convert to
 non-executable .tar, returns PharData object
 $phar = $phar-convert(Phar::EXE); // convert back to .phar.tar
 
 Didn't we just go full circle here? There was a proposed convert()
 method that did absolutely everything (on e-paper) and it was far less
 intuitive than when conversion was separated from compression. That's
 why you ended up implementing them separately, as I recall.

It does look similar, but the key difference here is that convert() was
a method that changed the underlying object.  If we return a new object,
this is a completely different ballpark, the current implementation
actually can remain the same and remove the intermediary files.

 This would also solve a subtle but important problem with the current
 conversion API where intermediary files are lying around.
 
 Can't we simply delete those intermediary files on success? That would
 be the normal procedure when renaming, no?

Actually, no.  The current implementation has no modification to the
original file on disk, as there is no way to know in advance if the user
actually intended to erase it, and it is actually impossible to do so if
there are any open references to the archive (i.e. Phar objects or
stream fp's lying around).

 Do you want to take a crack at a patch for any of these API features
 once they are worked out (buildFromDirectory should be an easy one, if
 you would like to start there)?

 Yes, I'm willing to help with it to a degree, as I said in a previous
 mail.

 How soon can we expect a patch for this?  Steph also expressed interest,
 and we are on a rather tight time schedule to get this to beta, which
 will mean a feature freeze (no new crap, just bug fixes).
 
 I'll implement buildFromDirectory() this weekend. It would've been last
 weekend, but I got caught up in trying to bring the last few non-core
 PECL modules into line over versioning structure, which hasn't been
 entirely plain sailing. (Still 5 + IBM to go.)

OK.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] phar API update

2008-04-09 Thread Gregory Beaver
Hi,

I've just implemented these features:

1) new getContents() method allows directly retrieving file contents. 
Here is a full-circle example:
?php
$phar = new Phar('blah.phar');
$phar['a.txt'] = 'hi';
echo $phar['a.txt']-getContents();
?

2) addFile/addEmptyDir/addFromString.  API is identical to ext/zip
?php
$phar = new Phar('blah.phar');
$phar-addEmptyDir('hello');
var_dump($phar['hello']-isDir());
$phar-addFile('/path/to/file.txt');
var_dump($phar['/path/to/file.txt']-getContents());
$phar-addFile('/path/to/file.txt', 'file.txt');
var_dump($phar['file.txt']-getContents());
$phar-addFromString('localname.txt', 'hi');
var_dump($phar['localname.txt']);
?

Still left to do:

1) fix up conversion/compression and decide how best to do this
2) buildFromDirectory (Steph)

Not going to do:

1) $phar['access']['directory']['this']['way']

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] phar['blah.php']-isWritable() works now

2008-04-09 Thread Gregory Beaver
Hi,

There were some rumblings about wanting a way to detect whether a
specific file/archive was writeable.  I made some small changes to the
way we detect this when the ini setting is changed, and added a test. 
Now the existing isWritable() from SplFileInfo always works properly for
Phar.  In addition, is_writeable/is_writable work, as does stat and
related functions, all of which were actually broken should one
ini_set() phar.readonly to another value.

http://news.php.net/php.pecl.cvs/10330

One step closer to satisfying the API grumblings :).

We need some assistance from Mac OS X experts, changes are needed to
make it compile on Tiger (and, apparently, on some Leopard systems that
upgraded from Tiger).

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: CVS Account Request: mimmi

2008-04-08 Thread Gregory Beaver
Thomas Mueller wrote:
 distributing a new package

Which package?  For what?

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] practical phar considerations

2008-04-08 Thread Gregory Beaver
Lars Strojny wrote:
 Hi Greg,
 
 Am Samstag, den 29.03.2008, 17:58 -0500 schrieb Greg Beaver:
 [...]
 If one uses file_put_contents('/path/to/this/file', 'hi') and 
 '/path/to/this' does not exist, there is an error.  The same is true of 
 fopen, regardless of mode.  mkdir() even fails unless the recursive 
 parameter is explicitly specified.  I do not think that this behavior 
 should be different in ext/phar, especially because all that is needed 
 is to create 1 directory (full/path/to/) and add the file.
 
 I mostly agree. Except that the whole argument chain applies to the
 current API. You mentioned mkdir(foo/bar/baz) triggering an error
 without the recursive argument, but Phar['foo/bar/baz'] does not.
 
 [... Performance concerns ...]
 $phar['long/path/to/subdir/file'] = 'hi';

 compared to:

 $phar['long']['path']['to']['subdir']['file'] = 'hi';

 is significantly slower.  Each [] results in a call to offsetGet and 
 instantiation of a new PharFileInfo object plus the final offsetSet call.
 
 Could you estimate how hard that performance hit would be?

We're talking about a similar difference between iterating over an array
and using an ArrayIterator, which is to say about 20 times slower.  This
is due to the many extra opcodes for each offset retrieval, which then
calls an expensive method call to offsetGet(), creates the directory
inside the phar archive, writes to disk, and continues.  Because we are
writing to disk, without a not-at-all-obvious startBuffering() call,
with large archives, the performance difference could be 100 times
slower or more.

In addition, although Phar does support the idea of thinking of archives
as multi-dimensional arrays, this is an abstraction not supported by the
actual archive file formats.  For other examples, take a look at at
ext/zip.  There is no support for opendir() in the stream wrapper of
ext/zip because it requires the kind of path grepping that pecl/phar
does.  Internally, no archive format stores paths the way directories
are stored in a typical file system.  In other words, typically a
directory is a file that contains a list of other files or directories.
 This allows very quick navigation on a random access disk, but causes
extreme bloat inside an archive.  Files are stored as full paths in what
is the equivalent of a single-dimensional array.  In other words, the
truth of the matter is that phar's ArrayAccess API is a 100% accurate
reflection of the true structure of the actual archives we are
accessing, and the iteration supported is a convenience for simulating
regular file systems.  The API you describe actually layers an
artificial complexity over this design, and as a result requires much
more code complexity.

Let's also remember we're talking about phar creation, which is going to
be far less common than phar usage.  To use a phar, you don't even need
to know what phar *is* let alone what the API is.  One just includes the
phar archive, or adds it to include_path with a phar:// stream wrapper path.

I've spent a significant amount of time actually implementing the new
read-only implementation of offsetGet() in the past day, and although I
think this might be possible I am running into a weird segfault in SPL
on shutdown caused by a double destruction of the object.  In addition,
the patch is not even close to complete, as it does not support the
addition of ArrayAccess to PharFileInfo, which would be required in
order to implement what your RFC describes.  The complexity of the patch
is reaching the hundreds of lines and will be in the thousands of lines,
all to add syntactic sugar that is far more inefficient than the current
syntax - is this really a necessary feature?

As Elizabeth points out, most people are going to build their iterator
by creating a directory structure and then add the entire directory all
at once.  Use of ArrayAccess to write to the archive would be done for
one or two files at most.

When reading from a phar, there is no real incentive to use relative
paths outside of scanning a directory for files (to locate drivers or
plugins, for instance), and iterating over the entire archive is usually
reserved for searching for a particular file.  The ability to glob
through a phar archive would of course be the most ideal solution for
that approach (perhaps globiterator already works?  I haven't tried it).

What I would like to do, however, is to rethink offsetSet().  I think
that we should introduce a property of PharFileInfo called content
that is read/write, and can be used to perform the equivalent of
file_get_contents()/file_put_contents().  This will allow a consistency
that is much more intuitive.  offsetSet() could then simply be removed,
or perhaps be refactored as a way to pass in a PharFileInfo and clone
the information.

 Yes, this shouldn't be allowed while
 $phar['foo/bar/baz'] = new DirectoryIterator(); could be allowed.

I will simply add makeEmptyDir() a la zip, although it is too bad
ext/zip never thought to 

Re: [PHP-DEV] Re: [RFC] Namespace syntax decision

2008-03-26 Thread Gregory Beaver
Marcus Boerger wrote:
 language out there that is in use and has anything like that. And even more
 scary to me, you did not solve anything by this because people still could
 write code prior to the namespace keyword. So no matter what we are screwed

?

[EMAIL PROTECTED]:~/workspace/php5$ cat test.php
?php
$a = 'before namespace';
namespace oops;
[EMAIL PROTECTED]:~/workspace/php5$ sapi/cli/php -n test.php

Fatal error: Namespace declaration statement has to be the very first
statement in the script in /home/cellog/workspace/php5/test.php on line 3

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] REMINDER - stream wrappers in include_path

2008-03-26 Thread Gregory Beaver
Marcus Boerger wrote:
 Hello Gregory,
 
 +   for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || 
 *p == '.'; p++);
 +   /* p - ptr  1 allows us to skip things like C:\whatever */
 +   if ((*p == ':')  (p - ptr  1)  (path_len - (p - path)  
 2)  (p[1] == '/')  (p[2] == '/')) {
 +   /* .:// or ..:// is not a stream wrapper */
 +   if (p[-1] != '.' || p[-2] != '.' || p - 2 != ptr) {
 +   p += 3;
 +   is_stream_wrapper = 1;
 +   }
 +   }
 
 You missed one part though. C stops execution of a boolean expression on
 the first one that decides on the result. So if p[1] is '\0' then p[2] will
 never be accessed. So there is no access violation at all.

good point (i.e. duh on my part).  attached patch removes that
unnecessary paranoia.

 Analyzing the check for '..:', took a long time :-) And I  like that we
 check for this common case without going to the wrapper list. And we do not
 need to check for the common case '.' either as you require two chars in
 front of the ':', cool!

I found a few minor optimizations of this code just now, attached patch
should be even better.

 
 However with the check below:
 
 +   if ((*p == ':')  (filename_length - (p - filename)  2)  (p[1] == 
 '/')  (p[2] == '/')) {
 +   wrapper = php_stream_locate_url_wrapper(filename, 
 actual_path, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC); 
 +   if (wrapper == php_plain_files_wrapper) {
 +   if (tsrm_realpath(actual_path, resolved_path 
 TSRMLS_CC)) {
 +   return estrdup(resolved_path);
 +   }
 +   }
 return NULL;
 
 Don't we need to check for wrapper being NULL as in:
 if (!wrapper || wrapper == php_plain_files_wrapper) {

Probably, I've added that in too.

Greg
Index: main/fopen_wrappers.c
===
RCS file: /repository/php-src/main/fopen_wrappers.c,v
retrieving revision 1.175.2.3.2.13.2.9
diff -u -r1.175.2.3.2.13.2.9 fopen_wrappers.c
--- main/fopen_wrappers.c   24 Mar 2008 09:30:41 -  
1.175.2.3.2.13.2.9
+++ main/fopen_wrappers.c   26 Mar 2008 20:01:04 -
@@ -447,14 +447,23 @@
char resolved_path[MAXPATHLEN];
char trypath[MAXPATHLEN];
const char *ptr, *end, *p;
+   char *actual_path;
+   php_stream_wrapper *wrapper;
 
if (!filename) {
return NULL;
}
 
-   /* Don't resolve paths which contain protocol */
+   /* Don't resolve paths which contain protocol (except of file://) */
for (p = filename; isalnum((int)*p) || *p == '+' || *p == '-' || *p == 
'.'; p++);
-   if ((*p == ':')  (p - filename  1)  (p[1] == '/')  (p[2] == 
'/')) {
+   /* checking for enough length after p to ensure we don't read past the 
end of filename */
+   if ((*p == ':')  (p[1] == '/')  (p[2] == '/')) {
+   wrapper = php_stream_locate_url_wrapper(filename, actual_path, 
STREAM_OPEN_FOR_INCLUDE TSRMLS_CC); 
+   if (!wrapper || wrapper == php_plain_files_wrapper) {
+   if (tsrm_realpath(actual_path, resolved_path 
TSRMLS_CC)) {
+   return estrdup(resolved_path);
+   }
+   }
return NULL;
}
 
@@ -473,7 +482,19 @@
 
ptr = path;
while (ptr  *ptr) {
-   end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
+   /* Check for stream wrapper */
+   int is_stream_wrapper = 0;
+
+   for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || *p 
== '.'; p++);
+   /* p - ptr  1 allows us to skip things like C:\whatever */
+   if ((*p == ':')  (p - ptr  1)  (p[1] == '/')  (p[2] == 
'/')) {
+   /* .:// or ..:// is not a stream wrapper */
+   if (p[-1] != '.' || p[-2] != '.' || p - 2 != ptr) {
+   p += 3;
+   is_stream_wrapper = 1;
+   }
+   }
+   end = strchr(p, DEFAULT_DIR_SEPARATOR);
if (end) {
if ((end-ptr) + 1 + filename_length + 1 = MAXPATHLEN) {
ptr = end + 1;
@@ -494,7 +515,23 @@
memcpy(trypath+len+1, filename, filename_length+1);
ptr = NULL;
}
-   if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
+   actual_path = trypath;
+   if (is_stream_wrapper) {
+   wrapper = php_stream_locate_url_wrapper(trypath, 
actual_path, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);  
+   if (!wrapper) {
+   continue;

Re: [PHP-DEV] REMINDER - stream wrappers in include_path

2008-03-25 Thread Gregory Beaver
Dmitry Stogov wrote:
 I hope it's the last iteration, but check me anyway.
 The patch is based on latest Gregory's patch.

 - optimized out strncpy() calls
 - zend_resolve_path() replaced with php_resolve_path()
 - improved php_resolve_path() to resolve file://...
 - fixed possible double-free issue in _php_stream_open_wrapper_ex()

 Thanks. Dmitry.

 Greg Beaver wrote:
 Andi Gutmans wrote:
 Can we please use strlcpy() instead of strncpy()? This is a coding
 standard we implemented years ago.

 obviously an easy change.  FYI - this also needs to be fixed in
 fopen_with_path_rel in PHP_5_2, as I copied most of the code from
 that function.

 Greg
works great here - commit with all due haste :)

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] REMINDER - stream wrappers in include_path

2008-03-25 Thread Gregory Beaver
Stanislav Malyshev wrote:
 stream wrapper.  Here is an example:

 oops.broken://UNC/path

 I wonder if .://UNC/path is treated as .+//UNC/path (and the same
 for ..). It should anyway :) However I'm not too worried without
 pathes like foo.bar - not likely to have path without any slashes
 unless it's . or .., and if you do, you always can say ./foo.bar

That's a great question.  In attempting to answer, I think I may have
unfortunately found a severe flaw in the patch, allowing reading past
the end of the filename and the include_path.

If we pass a file named hello: to php_resolve_path, this code:

if ((*p == ':')  (p - filename  1)  (p[1] == '/')  (p[2] == '/')) {

would look past the end of the filename by 1 (p[1] = '\0', but p[2] is
an off by one read).  Instead, we should be checking to see if p -
filename  filename_length - 2 so we have enough room for the stream
wrapper and 1 character (i.e. blah://a, not blah://).

To get around the problem Stas raises, we need to disallow . or ..
as stream wrapper names in php_stream_locate_url_wrapper and check
for them explicitly in php_resolve_path.

The attached patch is identical to Dmitry's wrapper6.patch.txt and fixes
these two issues.

Note that the check for . and .. is only needed when scanning
include_path, and the part at the end that checks dirname(__FILE__) does
not need it because there is no way __FILE__ could be
.://path/to/something or ..:/path/to/something if . and .. are
disallowed as stream wrapper names.

Unfortunately, I don't have quite enough time to get the attached patch
working, but I'm including it for the smarties to figure out how to
handle, I've put /* XXX FIXME */ where things need work.

Thanks,
Greg
Index: main/fopen_wrappers.c
===
RCS file: /repository/php-src/main/fopen_wrappers.c,v
retrieving revision 1.175.2.3.2.13.2.9
diff -u -r1.175.2.3.2.13.2.9 fopen_wrappers.c
--- main/fopen_wrappers.c   24 Mar 2008 09:30:41 -  
1.175.2.3.2.13.2.9
+++ main/fopen_wrappers.c   25 Mar 2008 19:00:36 -
@@ -447,14 +447,24 @@
char resolved_path[MAXPATHLEN];
char trypath[MAXPATHLEN];
const char *ptr, *end, *p;
+   char *actual_path;
+   php_stream_wrapper *wrapper;
+   int path_len = strlen(path);
 
if (!filename) {
return NULL;
}
 
-   /* Don't resolve paths which contain protocol */
+   /* Don't resolve paths which contain protocol (except of file://) */
for (p = filename; isalnum((int)*p) || *p == '+' || *p == '-' || *p == 
'.'; p++);
-   if ((*p == ':')  (p - filename  1)  (p[1] == '/')  (p[2] == 
'/')) {
+   /* XXX FIXME checking for enough length after p to ensure we don't read 
past the end of filename */
+   if ((*p == ':')  (p - filename = filename_length - 3)  (p[1] == 
'/')  (p[2] == '/')) {
+   wrapper = php_stream_locate_url_wrapper(filename, actual_path, 
STREAM_OPEN_FOR_INCLUDE TSRMLS_CC); 
+   if (wrapper == php_plain_files_wrapper) {
+   if (tsrm_realpath(actual_path, resolved_path 
TSRMLS_CC)) {
+   return estrdup(resolved_path);
+   }
+   }
return NULL;
}
 
@@ -473,7 +483,19 @@
 
ptr = path;
while (ptr  *ptr) {
-   end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
+   /* Check for stream wrapper */
+   int is_stream_wrapper = 0;
+
+   for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || *p 
== '.'; p++);
+   /* XXX FIXME checking for . or .. and also ensuring there is 
enough length left in include_path to check for // */
+   if ((*p == ':')  (p - ptr  1)  ((p + 1) - path = path_len 
- 3)  (p[1] == '/')  (p[2] == '/')) {
+   /* .:// or ..:// is not a stream wrapper */
+   if (!((p - ptr == 1  *(p - 1) == '.') || (p - ptr == 
2  *(p - 2) == '.'  *(p - 1) == '.'))) {
+   p += 3;
+   is_stream_wrapper = 1;
+   }
+   }
+   end = strchr(p, DEFAULT_DIR_SEPARATOR);
if (end) {
if ((end-ptr) + 1 + filename_length + 1 = MAXPATHLEN) {
ptr = end + 1;
@@ -494,7 +516,23 @@
memcpy(trypath+len+1, filename, filename_length+1);
ptr = NULL;
}
-   if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
+   actual_path = trypath;
+   if (is_stream_wrapper) {
+   wrapper = php_stream_locate_url_wrapper(trypath, 
actual_path, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);  
+   if (!wrapper) {
+   continue;
+   } else if (wrapper != 

Re: [PHP-DEV] REMINDER - stream wrappers in include_path

2008-03-25 Thread Gregory Beaver
Marcus Boerger wrote:
 Hello Gregory,
 
 Tuesday, March 25, 2008, 8:01:56 PM, you wrote:
 
 Stanislav Malyshev wrote:
 stream wrapper.  Here is an example:

 oops.broken://UNC/path
 I wonder if .://UNC/path is treated as .+//UNC/path (and the same
 for ..). It should anyway :) However I'm not too worried without
 pathes like foo.bar - not likely to have path without any slashes
 unless it's . or .., and if you do, you always can say ./foo.bar

 That's a great question.  In attempting to answer, I think I may have
 unfortunately found a severe flaw in the patch, allowing reading past
 the end of the filename and the include_path.
 
 If we pass a file named hello: to php_resolve_path, this code:
 
 if ((*p == ':')  (p - filename  1)  (p[1] == '/')  (p[2] == '/')) {
 
 would look past the end of the filename by 1 (p[1] = '\0', but p[2] is
 an off by one read).  Instead, we should be checking to see if p -
 filename  filename_length - 2 so we have enough room for the stream
 wrapper and 1 character (i.e. blah://a, not blah://).
 
 How so?
 
 Just reorder and put (p - filename  1 first)
snip

Hi Marcus,

It looks like I wasn't clear - the problem is not checking characters
before the :, but after.  With the existing code, if the string ended
with : the code would attempt the check : +1 and : + 2, which
could result in out-of-bounds read (read after the terminating '\0'.
However, in answer to your other question, we do need stream wrappers
longer than 1 character, as we would otherwise could be unnecessarily
checking drive letters on windows thinking they're stream wrappers.


However, I took your excellent suggestions into account in the attached
patch, which fully works and prevents use of either . or .. as stream
wrapper names.
Otherwise, its identical to wrapper6.patch.txt

One last check by Dmitry before commit and we should be good to go.
Thanks for the catch on the logical problem Stas and the coding
suggestions Marcus - this is the kind of teamwork that I dream of.  The
open source gods must be looking down on us kindly.

Greg
Index: main/fopen_wrappers.c
===
RCS file: /repository/php-src/main/fopen_wrappers.c,v
retrieving revision 1.175.2.3.2.13.2.9
diff -u -r1.175.2.3.2.13.2.9 fopen_wrappers.c
--- main/fopen_wrappers.c   24 Mar 2008 09:30:41 -  
1.175.2.3.2.13.2.9
+++ main/fopen_wrappers.c   26 Mar 2008 03:43:28 -
@@ -447,14 +447,24 @@
char resolved_path[MAXPATHLEN];
char trypath[MAXPATHLEN];
const char *ptr, *end, *p;
+   char *actual_path;
+   php_stream_wrapper *wrapper;
+   int path_len = strlen(path);
 
if (!filename) {
return NULL;
}
 
-   /* Don't resolve paths which contain protocol */
+   /* Don't resolve paths which contain protocol (except of file://) */
for (p = filename; isalnum((int)*p) || *p == '+' || *p == '-' || *p == 
'.'; p++);
-   if ((*p == ':')  (p - filename  1)  (p[1] == '/')  (p[2] == 
'/')) {
+   /* checking for enough length after p to ensure we don't read past the 
end of filename */
+   if ((*p == ':')  (filename_length - (p - filename)  2)  (p[1] == 
'/')  (p[2] == '/')) {
+   wrapper = php_stream_locate_url_wrapper(filename, actual_path, 
STREAM_OPEN_FOR_INCLUDE TSRMLS_CC); 
+   if (wrapper == php_plain_files_wrapper) {
+   if (tsrm_realpath(actual_path, resolved_path 
TSRMLS_CC)) {
+   return estrdup(resolved_path);
+   }
+   }
return NULL;
}
 
@@ -473,7 +483,19 @@
 
ptr = path;
while (ptr  *ptr) {
-   end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
+   /* Check for stream wrapper */
+   int is_stream_wrapper = 0;
+
+   for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || *p 
== '.'; p++);
+   /* p - ptr  1 allows us to skip things like C:\whatever */
+   if ((*p == ':')  (p - ptr  1)  (path_len - (p - path)  2) 
 (p[1] == '/')  (p[2] == '/')) {
+   /* .:// or ..:// is not a stream wrapper */
+   if (p[-1] != '.' || p[-2] != '.' || p - 2 != ptr) {
+   p += 3;
+   is_stream_wrapper = 1;
+   }
+   }
+   end = strchr(p, DEFAULT_DIR_SEPARATOR);
if (end) {
if ((end-ptr) + 1 + filename_length + 1 = MAXPATHLEN) {
ptr = end + 1;
@@ -494,7 +516,23 @@
memcpy(trypath+len+1, filename, filename_length+1);
ptr = NULL;
}
-   if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
+   actual_path = trypath;
+   if (is_stream_wrapper) {
+   wrapper = 

Re: [PHP-DEV] REMINDER - stream wrappers in include_path

2008-03-24 Thread Gregory Beaver
Dmitry Stogov wrote:
 Hi Greg,

 In your second patch you forgot break, so it couldn't work.
 I don't see any reason in second patch at all, because you call
 php_resolve_patch() from _php_stream_open_wrapper_ex() anyway.

 The bad thing with the first part that it calls realpath() function
 twice for each include(relative_path.php) and it makes several
 file-system accesses (look into `strace ... 21| grep lstat`). With
 your patch I see 6 syscalls more.

 So I would prefer my patch that is more efficient for regular files.
 The same patch with fixed white-spaces is attached. 

Your patch is broken, it causes an endless loop in
tests/include_path.phpt when running phar tests.

Incidentally, I was unaware of the strace command (I've seen it bandied
about on irc, but thought it was something else), so thank you for
edumacatin me there.

The attached patch has no additional syscalls over the current case for
both existing and non-existing files, and actually works for phar as
well :).  It's also simpler (I removed the include stuff from
zend_vm_def.h), although you may want to add it back in and bench it to
see if it makes any difference in performance, since I found such a
dramatic reduction in operations here with it.

Greg
Index: main/fopen_wrappers.c
===
RCS file: /repository/php-src/main/fopen_wrappers.c,v
retrieving revision 1.175.2.3.2.13.2.9
diff -u -r1.175.2.3.2.13.2.9 fopen_wrappers.c
--- main/fopen_wrappers.c   24 Mar 2008 09:30:41 -  
1.175.2.3.2.13.2.9
+++ main/fopen_wrappers.c   24 Mar 2008 13:24:34 -
@@ -473,7 +473,15 @@
 
ptr = path;
while (ptr  *ptr) {
-   end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
+   /* Check for stream wrapper */
+   int is_stream_wrapper = 0;
+
+   for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || *p 
== '.'; p++);
+   if ((*p == ':')  (p - ptr  1)  (p[1] == '/')  (p[2] == 
'/')) {
+   p += 2;
+   is_stream_wrapper = 1;
+   }
+   end = strchr(p, DEFAULT_DIR_SEPARATOR);
if (end) {
if ((end-ptr) + 1 + filename_length + 1 = MAXPATHLEN) {
ptr = end + 1;
@@ -494,6 +502,25 @@
memcpy(trypath+len+1, filename, filename_length+1);
ptr = NULL;
}
+   if (is_stream_wrapper) {
+   char *actual;
+   php_stream_wrapper *wrapper = 
php_stream_locate_url_wrapper(trypath, actual, STREAM_OPEN_FOR_INCLUDE 
TSRMLS_CC);
+   
+   if (!wrapper) {
+   continue;
+   } else if (wrapper == php_plain_files_wrapper) {
+   strncpy(trypath, actual, MAXPATHLEN);
+   } else {
+   if (wrapper-wops-url_stat) {
+   php_stream_statbuf ssb;
+
+   if (SUCCESS == 
wrapper-wops-url_stat(wrapper, trypath, 0, ssb, NULL TSRMLS_CC)) {
+   return estrdup(trypath);
+   }
+   }
+   continue;
+   }
+   }
if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
return estrdup(resolved_path);
}
@@ -511,6 +538,29 @@
exec_fname_length + 1 + filename_length + 1  MAXPATHLEN) {
memcpy(trypath, exec_fname, exec_fname_length + 1);
memcpy(trypath+exec_fname_length + 1, filename, 
filename_length+1);
+
+   /* Check for stream wrapper */
+   for (p = trypath; isalnum((int)*p) || *p == '+' || *p 
== '-' || *p == '.'; p++);
+   if ((*p == ':')  (p - trypath  1)  (p[1] == '/') 
 (p[2] == '/')) {
+   char *actual;
+   php_stream_wrapper *wrapper = 
php_stream_locate_url_wrapper(trypath, actual, STREAM_OPEN_FOR_INCLUDE 
TSRMLS_CC);
+   
+   if (!wrapper) {
+   return NULL;
+   } else if (wrapper == php_plain_files_wrapper) 
{
+   strncpy(trypath, actual, MAXPATHLEN);
+   } else {
+   if (wrapper-wops-url_stat) {
+   php_stream_statbuf ssb;
+
+   if (SUCCESS == 
wrapper-wops-url_stat(wrapper, trypath, 0, ssb, NULL TSRMLS_CC)) {
+   return 

Re: [PHP-DEV] REMINDER - stream wrappers in include_path

2008-03-24 Thread Gregory Beaver
Marcus Boerger wrote:
 Hello Gregory,

 Monday, March 24, 2008, 2:28:00 PM, you wrote:

   
 Index: main/fopen_wrappers.c
 ===
 RCS file: /repository/php-src/main/fopen_wrappers.c,v
 retrieving revision 1.175.2.3.2.13.2.9
 diff -u -r1.175.2.3.2.13.2.9 fopen_wrappers.c
 --- main/fopen_wrappers.c   24 Mar 2008 09:30:41 -  
 1.175.2.3.2.13.2.9
 +++ main/fopen_wrappers.c   24 Mar 2008 13:24:34 -
 @@ -473,7 +473,15 @@
  
 ptr = path;
 while (ptr  *ptr) {
 -   end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
 +   /* Check for stream wrapper */
 +   int is_stream_wrapper = 0;
 +
 +   for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || 
 *p == '.'; p++);
 +   if ((*p == ':')  (p - ptr  1)  (p[1] == '/')  (p[2] 
 == '/')) {
 
 However how about:
 if ((p  ptr)  !memcmp(p, ://, 3)) {
this would unfortunately break UNC paths on unix, which start with //. 
We have to verify that the stuff between : and : in the previous thing
is a valid stream wrapper, which means it can only be
alphanumeric/+/-/.  However, I imagine the memcmp could be applied as if
((*p == ':')  (p - ptr  1)  !memcmp(p, ://, 3))

Would that really be faster?
 I think prefixinf with STREAMS_ would be good.
OK, updated and attached

Greg
Index: main/fopen_wrappers.c
===
RCS file: /repository/php-src/main/fopen_wrappers.c,v
retrieving revision 1.175.2.3.2.13.2.9
diff -u -r1.175.2.3.2.13.2.9 fopen_wrappers.c
--- main/fopen_wrappers.c   24 Mar 2008 09:30:41 -  
1.175.2.3.2.13.2.9
+++ main/fopen_wrappers.c   24 Mar 2008 13:46:39 -
@@ -473,7 +473,15 @@
 
ptr = path;
while (ptr  *ptr) {
-   end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
+   /* Check for stream wrapper */
+   int is_stream_wrapper = 0;
+
+   for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || *p 
== '.'; p++);
+   if ((*p == ':')  (p - ptr  1)  (p[1] == '/')  (p[2] == 
'/')) {
+   p += 2;
+   is_stream_wrapper = 1;
+   }
+   end = strchr(p, DEFAULT_DIR_SEPARATOR);
if (end) {
if ((end-ptr) + 1 + filename_length + 1 = MAXPATHLEN) {
ptr = end + 1;
@@ -494,6 +502,25 @@
memcpy(trypath+len+1, filename, filename_length+1);
ptr = NULL;
}
+   if (is_stream_wrapper) {
+   char *actual;
+   php_stream_wrapper *wrapper = 
php_stream_locate_url_wrapper(trypath, actual, STREAM_OPEN_FOR_INCLUDE 
TSRMLS_CC);
+   
+   if (!wrapper) {
+   continue;
+   } else if (wrapper == php_plain_files_wrapper) {
+   strncpy(trypath, actual, MAXPATHLEN);
+   } else {
+   if (wrapper-wops-url_stat) {
+   php_stream_statbuf ssb;
+
+   if (SUCCESS == 
wrapper-wops-url_stat(wrapper, trypath, 0, ssb, NULL TSRMLS_CC)) {
+   return estrdup(trypath);
+   }
+   }
+   continue;
+   }
+   }
if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
return estrdup(resolved_path);
}
@@ -511,6 +538,29 @@
exec_fname_length + 1 + filename_length + 1  MAXPATHLEN) {
memcpy(trypath, exec_fname, exec_fname_length + 1);
memcpy(trypath+exec_fname_length + 1, filename, 
filename_length+1);
+
+   /* Check for stream wrapper */
+   for (p = trypath; isalnum((int)*p) || *p == '+' || *p 
== '-' || *p == '.'; p++);
+   if ((*p == ':')  (p - trypath  1)  (p[1] == '/') 
 (p[2] == '/')) {
+   char *actual;
+   php_stream_wrapper *wrapper = 
php_stream_locate_url_wrapper(trypath, actual, STREAM_OPEN_FOR_INCLUDE 
TSRMLS_CC);
+   
+   if (!wrapper) {
+   return NULL;
+   } else if (wrapper == php_plain_files_wrapper) 
{
+   strncpy(trypath, actual, MAXPATHLEN);
+   } else {
+   if (wrapper-wops-url_stat) {
+   php_stream_statbuf ssb;
+
+   if (SUCCESS == 

Re: [PHP-DEV] Re: [PECL-DEV] About that PECL versioning thing

2008-03-24 Thread Gregory Beaver
Steph Fox wrote:
 Hello Pierre,
 
  Aside from Pierre's arguments in favour of using package.xml to set the
  extension version (which 3 PECL extensions - two of them Pierre's -
 do at
  present), does anyone have any objection to the proposal at
  http://wiki.php.net/rfc/peclversioning?

 I'm not in favour of using package.xml to set the version. I'm in
 favour of allowing package.xml usage.
 
 Nobody's attempting to prevent package.xml usage, least of all me! I
 actually want to extend package.xml to give more information (QA
 related) so that people have more of a clue about what they're dealing
 with. E.g. code coverage %, maintenance status, whether the package is
 of general/special interest (this last mostly for hosting companies) and
 some kind of grading system. But this is all open to discussion and
 probably won't happen for a long while.

This kind of meta-data doesn't belong in a package.xml, but it would
make perfect sense to host it through REST on pecl.php.net.  Don't
forget, package.xml is used by external channels as well, and they have
completely different requirements.

package.xml is intended to be used by the pear installer to install
packages and provide essential metadata only.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] REMINDER - stream wrappers in include_path

2008-03-24 Thread Gregory Beaver
Dmitry Stogov wrote:
 REALPATH_FAILED looks like a hack :(
 PHP itself doesn't need it at all, according to your patch
 php_stream_open() may just return NULL immediately instead of setting
 of this flag.
 However I am not sure that it will work for all cases. The fact that
 we cannot resolve the path doesn't mean that we cannot open the file.
 (On some systems getcwd() may fail on some reasons).
I remember Solaris having issues with this, now that you mention it.

However, the place that I added this already returned NULL if realpath
fails, it doesn't change the behavior, just moves the realpath to an
earlier position and eliminates an unnecessary double call.  However, if
we are comfortable having the double realpath on files not found in
include_path (this would only have a performance affect on apps with
lots of conditional loading of drivers where the majority are not
found), this is fine with me.  I've attached a patch that removes
REALPATH_FAILED so there are options.

Another option would be to determine which OSes this can fail, and
simply not use REALPATH_FAILED on those OSes.
 I didn't test the patch with pecl/phar.
 Could you explain why php goes into the endless loop?
because the cut/paste to plain_wrapper.c:1419 needs a ptr = end, unlike
the code in fopen_wrappers.c.  Once you fix this problem, then the real
logic problem rears its head, which is that we go into plain_wrapper to
open an external stream wrapper.  It is far less efficient (about 4-6%
by my measurements) to do this, which is why I moved the include_path
parsing into streams.c

This bug only happens when the last item in include_path is a stream
wrapper and the file is not found in include_path.

Greg
Index: main/fopen_wrappers.c
===
RCS file: /repository/php-src/main/fopen_wrappers.c,v
retrieving revision 1.175.2.3.2.13.2.9
diff -u -r1.175.2.3.2.13.2.9 fopen_wrappers.c
--- main/fopen_wrappers.c   24 Mar 2008 09:30:41 -  
1.175.2.3.2.13.2.9
+++ main/fopen_wrappers.c   24 Mar 2008 14:39:45 -
@@ -473,7 +473,15 @@
 
ptr = path;
while (ptr  *ptr) {
-   end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
+   /* Check for stream wrapper */
+   int is_stream_wrapper = 0;
+
+   for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || *p 
== '.'; p++);
+   if ((*p == ':')  (p - ptr  1)  (p[1] == '/')  (p[2] == 
'/')) {
+   p += 2;
+   is_stream_wrapper = 1;
+   }
+   end = strchr(p, DEFAULT_DIR_SEPARATOR);
if (end) {
if ((end-ptr) + 1 + filename_length + 1 = MAXPATHLEN) {
ptr = end + 1;
@@ -494,6 +502,25 @@
memcpy(trypath+len+1, filename, filename_length+1);
ptr = NULL;
}
+   if (is_stream_wrapper) {
+   char *actual;
+   php_stream_wrapper *wrapper = 
php_stream_locate_url_wrapper(trypath, actual, STREAM_OPEN_FOR_INCLUDE 
TSRMLS_CC);
+   
+   if (!wrapper) {
+   continue;
+   } else if (wrapper == php_plain_files_wrapper) {
+   strncpy(trypath, actual, MAXPATHLEN);
+   } else {
+   if (wrapper-wops-url_stat) {
+   php_stream_statbuf ssb;
+
+   if (SUCCESS == 
wrapper-wops-url_stat(wrapper, trypath, 0, ssb, NULL TSRMLS_CC)) {
+   return estrdup(trypath);
+   }
+   }
+   continue;
+   }
+   }
if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
return estrdup(resolved_path);
}
@@ -511,6 +538,29 @@
exec_fname_length + 1 + filename_length + 1  MAXPATHLEN) {
memcpy(trypath, exec_fname, exec_fname_length + 1);
memcpy(trypath+exec_fname_length + 1, filename, 
filename_length+1);
+
+   /* Check for stream wrapper */
+   for (p = trypath; isalnum((int)*p) || *p == '+' || *p 
== '-' || *p == '.'; p++);
+   if ((*p == ':')  (p - trypath  1)  (p[1] == '/') 
 (p[2] == '/')) {
+   char *actual;
+   php_stream_wrapper *wrapper = 
php_stream_locate_url_wrapper(trypath, actual, STREAM_OPEN_FOR_INCLUDE 
TSRMLS_CC);
+   
+   if (!wrapper) {
+   return NULL;
+   } else if (wrapper == php_plain_files_wrapper) 
{
+

Re: [PHP-DEV] REMINDER - stream wrappers in include_path

2008-03-24 Thread Gregory Beaver
Dmitry Stogov wrote:


 Gregory Beaver wrote:
 Dmitry Stogov wrote:
 REALPATH_FAILED looks like a hack :(
 PHP itself doesn't need it at all, according to your patch
 php_stream_open() may just return NULL immediately instead of setting
 of this flag.
 However I am not sure that it will work for all cases. The fact that
 we cannot resolve the path doesn't mean that we cannot open the file.
 (On some systems getcwd() may fail on some reasons).
 I remember Solaris having issues with this, now that you mention it.

 However, the place that I added this already returned NULL if realpath
 fails, it doesn't change the behavior, just moves the realpath to an
 earlier position and eliminates an unnecessary double call.  However, if
 we are comfortable having the double realpath on files not found in
 include_path (this would only have a performance affect on apps with
 lots of conditional loading of drivers where the majority are not
 found), this is fine with me.  I've attached a patch that removes
 REALPATH_FAILED so there are options.

 Another option would be to determine which OSes this can fail, and
 simply not use REALPATH_FAILED on those OSes.
 I didn't test the patch with pecl/phar.
 Could you explain why php goes into the endless loop?
 because the cut/paste to plain_wrapper.c:1419 needs a ptr = end, unlike
 the code in fopen_wrappers.c.

 You are right.

 Once you fix this problem, then the real
 logic problem rears its head, which is that we go into plain_wrapper to
 open an external stream wrapper.  It is far less efficient (about 4-6%
 by my measurements) to do this, which is why I moved the include_path
 parsing into streams.c

 Did you measure pecl/phar or regular files?
I only measured regular files, my concern is that we don't affect any
existing users, 100% of whom use regular files at the moment (obviously :).

 This bug only happens when the last item in include_path is a stream
 wrapper and the file is not found in include_path.

 In general I don't have objections except of changing
 zend_resolve_path() (which is a callback for ZE) into
 php_resolve_path(). Anyway I'll look into patch once again with fresh
 head.

 I would also ask Stas and other interested people to look into it. 

Thanks Dmitry,

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] REMINDER - stream wrappers in include_path

2008-03-24 Thread Gregory Beaver
Stanislav Malyshev wrote:
 this would unfortunately break UNC paths on unix, which start with //. 
 
 Unix has UNC paths?

Beats me, I'm sure posix-based systems don't, but it is called Uniform
Naming Convention so it's possible somebody might implement it
(http://en.wikipedia.org/wiki/Path_(computing)#Uniform_Naming_Convention).

:)
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: [PECL-DEV] About that PECL versioning thing

2008-03-24 Thread Gregory Beaver
Steph Fox wrote:
 What a horrible name :) How about pecl_graveyard?

siberia

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: [RFC] Namespace syntax decision

2008-03-22 Thread Gregory Beaver
Marcus Boerger wrote:
 Hello Internals,
 
   we all were asked to stop discussing syntax of namespaces as we were told
 that we would decide after the namespace functionality was fully implemented.
 Now I think that the functionallity is pretty much settled we should
 revisit the syntax. We all have been very patient so far. Anyway here goes
 my take on it:
 
 PHP is very close to Java and C++ in terms of Syntax. And many of our users
 are familiar with one or even both of them. Also we have a tendency to
 especially take syntax from those two or be in line with those two
 languages. That said I see two ways:
 
 1) namespace foo { }
 
 2) package foo;

I did not notice until now that you had changed the keyword to package.
 -1 on this change.  Either namespace blah; or namespace blah {}.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: [RFC] Namespace syntax decision

2008-03-22 Thread Gregory Beaver
Felipe Pena wrote:
 Em Sex, 2008-03-21 às 17:01 -0500, Gregory Beaver escreveu:
 1) namespace foo { }
 This is acceptable if nothing can exist outside namespace foo {} except
 declare and other namespace declarations.

 
 Indeed!
 
 Here's my try:
 http://felipe.ath.cx/diff/namespace.diff
 http://felipe.ath.cx/diff/namespace.phpt
 

Hi Felipe,

The patch is pristine coding, but I do think the error message needs
some loving:

+   if (zend_do_namespace_check(TSRMLS_C) == FAILURE) {
+   zend_error(E_COMPILE_ERROR, Only namespace declaration 
is allowed
in the script);

This implies that only namespace is allowed, and would be confusing to
99% of users.  Might I suggest this error message instead:

This script contains namespaces, all other code must be contained
within namespace declarations

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] short_open_tag

2008-03-22 Thread Gregory Beaver
Stefan Walk wrote:
 Johannes Schlüter schrieb:
 Now we have the big issue: Do we want to have short open tags forever?
 Well, without tooo much thinking my idea would be to drop ? but keep
 ?=, ?= shouldn't conflict with ?xml tags in the same file, but
 make it simple to do templating using PHP, on the other hand when not
 echo'ing stuff you already have to write more soo the four additional
 characters (php ) don't matter that much - especially every decent
 editor/ide should be able to give you a completion on that, if you want.
 
 ul
 ? foreach ($items as $item): ?
 li?=$item?/li
 ? endforeach ?
 /ul
 
 you can have short stuff without outputting stuff too.

I see many good reasons to disable short open tags.  However, there is a
compromise that is better from all vantage points:

ul
?p foreach ($items as $item): ?
li?=$item ?/li
?p endforeach ?
/ul

?p is a valid PI and would prevent ?xml from being parsed as PHP.
Also legal is ?: as PI's can start with or contain : or _.  Honestly
though, this is not so important to me, my primary concern is the
conflict with ?xml.  I mention it out of deference for those who
actually do care about writing scripts that are xml-compliant for some
strange reason :).  Also possible and relatively simple to implement
would be to allow an = at the start of an expression to alias to T_ECHO,
so that ?p =$item ? would work like ?=$item?.  This is, however,
very perl-ish, so I mention it only as a possible way to preserve that
aspect of short tags for template usage.  God forbid we start seeing
regular scripts using = to mean echo :).

As a note, I use exclusively ?php in my templates and also use ?xml to
generate xhtml, so I am very much against per-script enabling of short
tag ? for the annoyance it would introduce of forcing an ini_set() at
the top of each template and the bottom as well to be a good citizen and
restore the old value.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] REMINDER - stream wrappers in include_path

2008-03-21 Thread Gregory Beaver
Dmitry Stogov wrote:
 Hi Greg,

 I've fixed your patch to work with all functions (fopen,
 file_get_contente).
 Please verify it with ext/phar and then I'll commit it.

 Thanks. Dmitry.

 Gregory Beaver wrote:
 Hi,

 Please look at the stream wrappers in include_path patch I posted
 last week.

 Thanks,
 Greg

Hi Dmitry,

the patch has a few major problems and a few minor ones.  First off,
there are spaces instead of tabs, which is not a huge deal, I've
corrected that in the attached patch.

It is, however, logically void to do stream wrapper operations in
plain_wrapper.c.  I removed that code entirely.  Instead, the path
resolve is now done in php_stream_open_wrapper_ex where it belongs,
before determining which stream wrapper to open.  This will result in a
double call to the function when calling include, but because the 2nd
call will simply return after determining it has received a full path.

I've attached 2 patches (apparently, Zend is not included in cvs diff -u
of php5), 1 for adding path resolution to include/require (this is a
significant performance improvement over the existing code).  The second
patch adds stream wrapper support to both php_resolve_path and
_php_stream_open_wrapper_ex, which automatically gives stream wrapper in
include_path support to all current and future functions that use
include_path.

Greg
Index: main/fopen_wrappers.c
===
RCS file: /repository/php-src/main/fopen_wrappers.c,v
retrieving revision 1.175.2.3.2.13.2.8
diff -u -r1.175.2.3.2.13.2.8 fopen_wrappers.c
--- main/fopen_wrappers.c   13 Mar 2008 14:09:54 -  
1.175.2.3.2.13.2.8
+++ main/fopen_wrappers.c   21 Mar 2008 16:50:45 -
@@ -452,11 +452,11 @@
return NULL;
}
 
-   /* Don't resolve patches which contain protocol */
+   /* Don't resolve paths which contain protocol */
for (p = filename; isalnum((int)*p) || *p == '+' || *p == '-' || *p == 
'.'; p++);
-if ((*p == ':')  (p - filename  1)  (p[1] == '/')  (p[2] == '/')) {
-   return NULL;
-}
+   if ((*p == ':')  (p - filename  1)  (p[1] == '/')  (p[2] == 
'/')) {
+   return NULL;
+   }
 
if ((*filename == '.'  
 (IS_SLASH(filename[1]) || 
@@ -473,7 +473,15 @@
 
ptr = path;
while (ptr  *ptr) {
-   end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
+   /* Check for stream wrapper */
+   int is_stream_wrapper = 0;
+
+   for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || *p 
== '.'; p++);
+   if ((*p == ':')  (p - ptr  1)  (p[1] == '/')  (p[2] == 
'/')) {
+   p += 2;
+   is_stream_wrapper = 1;
+   }
+   end = strchr(p, DEFAULT_DIR_SEPARATOR);
if (end) {
if ((end-ptr) + 1 + filename_length + 1 = MAXPATHLEN) {
ptr = end + 1;
@@ -494,6 +502,25 @@
memcpy(trypath+len+1, filename, filename_length+1);
ptr = NULL;
}
+   if (is_stream_wrapper) {
+   char *actual;
+   php_stream_wrapper *wrapper = 
php_stream_locate_url_wrapper(trypath, actual, STREAM_OPEN_FOR_INCLUDE 
TSRMLS_CC);
+   
+   if (!wrapper) {
+   continue;
+   } else if (wrapper == php_plain_files_wrapper) {
+   strncpy(trypath, actual, MAXPATHLEN);
+   } else {
+   if (wrapper-wops-url_stat) {
+   php_stream_statbuf ssb;
+
+   if (SUCCESS == 
wrapper-wops-url_stat(wrapper, trypath, 0, ssb, NULL TSRMLS_CC)) {
+   return estrdup(trypath);
+   }
+   }
+   continue;
+   }
+   }
if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
return estrdup(resolved_path);
}
@@ -511,6 +538,29 @@
exec_fname_length + 1 + filename_length + 1  MAXPATHLEN) {
memcpy(trypath, exec_fname, exec_fname_length + 1);
memcpy(trypath+exec_fname_length + 1, filename, 
filename_length+1);
+
+   /* Check for stream wrapper */
+   for (p = trypath; isalnum((int)*p) || *p == '+' || *p 
== '-' || *p == '.'; p++);
+   if ((*p == ':')  (p - trypath  1)  (p[1] == '/')  
(p[2] == '/')) {
+   char *actual;
+   php_stream_wrapper *wrapper = 
php_stream_locate_url_wrapper(trypath, actual, STREAM_OPEN_FOR_INCLUDE 
TSRMLS_CC

[PHP-DEV] Re: [RFC] Namespace syntax decision

2008-03-21 Thread Gregory Beaver
Marcus Boerger wrote:
 Hello Internals,
 
   we all were asked to stop discussing syntax of namespaces as we were told
 that we would decide after the namespace functionality was fully implemented.
 Now I think that the functionallity is pretty much settled we should
 revisit the syntax. We all have been very patient so far. Anyway here goes
 my take on it:
 
 PHP is very close to Java and C++ in terms of Syntax. And many of our users
 are familiar with one or even both of them. Also we have a tendency to
 especially take syntax from those two or be in line with those two
 languages. That said I see two ways:
 
 1) namespace foo { }

This is acceptable if nothing can exist outside namespace foo {} except
declare and other namespace declarations.

 
 2) package foo;
 
 I favor 1) if we allow namespace nesting and 2) if not. The current way of
 nesting is very confusing:
 namespace foo; namespace bar;

I prefer this syntax because it discourages multiple namespaces, but
still allows them (nesting is an inaccurate term in this case, I
strongly encourage not using it)

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] REMINDER - stream wrappers in include_path

2008-03-20 Thread Gregory Beaver
Hi,

Please look at the stream wrappers in include_path patch I posted last week.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] profiling followup on addition of streams to include_path - it's *faster*

2008-03-08 Thread Gregory Beaver
Alexey Zakhlestin wrote:
 what about including(_once) by absolute path?
   

Hi,

There is no difference from the existing code for include_once, the
first line of php_resolve_path has a check for IS_ABSOLUTE_PATH, all of
the code I wrote follows this line.  Calls to include (no _once) would
add 1 function call to php_resolve_path, an insignificant difference.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] [PATCH] fast streams support in include_path

2008-03-08 Thread Gregory Beaver
Hi,

Here's the last attempt at streams support in include_path. 

After siccing callgrind on the patch, I'm confident it meets performance
requirements.  Even in the worst case, it is significantly faster than
PHP 5.2, and insignificantly slower (1%) than the current CVS.

This patch is optimized so that it is:
1% faster than the current implementation for include/require
1% slower than current include_once/require_once implementation

It also fixes a compile warning caused by missing cast from const char *
to char *

Greg
Index: Zend/zend_vm_def.h
===
RCS file: /repository/ZendEngine2/zend_vm_def.h,v
retrieving revision 1.59.2.29.2.48.2.41
diff -u -r1.59.2.29.2.48.2.41 zend_vm_def.h
--- Zend/zend_vm_def.h  5 Mar 2008 13:34:12 -   1.59.2.29.2.48.2.41
+++ Zend/zend_vm_def.h  8 Mar 2008 18:35:06 -
@@ -3091,8 +3091,19 @@
}
break;
case ZEND_INCLUDE:
-   case ZEND_REQUIRE:
-   new_op_array = 
compile_filename(Z_LVAL(opline-op2.u.constant), inc_filename TSRMLS_CC);
+   case ZEND_REQUIRE: {
+   char *resolved_path;
+
+   resolved_path = 
zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC);
+   if (resolved_path) {
+   zval rz;
+   ZVAL_STRINGL(rz, resolved_path, 
strlen(resolved_path), 0);
+   new_op_array = 
compile_filename(Z_LVAL(opline-op2.u.constant), rz TSRMLS_CC);
+   efree(resolved_path);
+   } else {
+   new_op_array = 
compile_filename(Z_LVAL(opline-op2.u.constant), inc_filename TSRMLS_CC);
+   }
+   }
break;
case ZEND_EVAL: {
char *eval_desc = 
zend_make_compiled_string_description(eval()'d code TSRMLS_CC);
Index: Zend/zend_vm_execute.h
===
RCS file: /repository/ZendEngine2/zend_vm_execute.h,v
retrieving revision 1.62.2.30.2.49.2.40
diff -u -r1.62.2.30.2.49.2.40 zend_vm_execute.h
--- Zend/zend_vm_execute.h  5 Mar 2008 13:34:12 -   
1.62.2.30.2.49.2.40
+++ Zend/zend_vm_execute.h  8 Mar 2008 18:35:22 -
@@ -1700,8 +1700,19 @@
}
break;
case ZEND_INCLUDE:
-   case ZEND_REQUIRE:
-   new_op_array = 
compile_filename(Z_LVAL(opline-op2.u.constant), inc_filename TSRMLS_CC);
+   case ZEND_REQUIRE: {
+   char *resolved_path;
+
+   resolved_path = 
zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC);
+   if (resolved_path) {
+   zval rz;
+   ZVAL_STRINGL(rz, resolved_path, 
strlen(resolved_path), 0);
+   new_op_array = 
compile_filename(Z_LVAL(opline-op2.u.constant), rz TSRMLS_CC);
+   efree(resolved_path);
+   } else {
+   new_op_array = 
compile_filename(Z_LVAL(opline-op2.u.constant), inc_filename TSRMLS_CC);
+   }
+   }
break;
case ZEND_EVAL: {
char *eval_desc = 
zend_make_compiled_string_description(eval()'d code TSRMLS_CC);
@@ -4885,8 +4896,19 @@
}
break;
case ZEND_INCLUDE:
-   case ZEND_REQUIRE:
-   new_op_array = 
compile_filename(Z_LVAL(opline-op2.u.constant), inc_filename TSRMLS_CC);
+   case ZEND_REQUIRE: {
+   char *resolved_path;
+
+   resolved_path = 
zend_resolve_path(Z_STRVAL_P(inc_filename), Z_STRLEN_P(inc_filename) TSRMLS_CC);
+   if (resolved_path) {
+   zval rz;
+   ZVAL_STRINGL(rz, resolved_path, 
strlen(resolved_path), 0);
+   new_op_array = 
compile_filename(Z_LVAL(opline-op2.u.constant), rz TSRMLS_CC);
+   efree(resolved_path);
+   } else {
+   new_op_array = 
compile_filename(Z_LVAL(opline-op2.u.constant), inc_filename TSRMLS_CC);
+   }
+   }
break;
case ZEND_EVAL: {
 

Re: [PHP-DEV] Re: 5.3 Release Planning

2008-03-07 Thread Gregory Beaver
Antony Dovgal wrote:
 On 07.03.2008 05:43, Gregory Beaver wrote:
 Just a quick note: I'd like to consider another possible approach,
 having pecl/phar synced from stable pecl release.  
 
 I'm not sure it's good idea.
 IMO it should go trough much more thorough testing to be included into the 
 core.

Hi,

I wholeheartedly agree that phar needs more testing.  I also think some
other areas of php could have used more testing, such as the serious
issues I found in zlib stream filters, but they were useful for years
even with edge case flaws.  Areas that I know phar needs work:

 * big-endian like PPC tar/zip support is incomplete, I need to write
the simple byte order reversal that will complete this, and add the same
compiler flags to the tar struct that we use on zip structs.  This is an
easy fix.
 * finishing up include_path support for streams.  Other threads address
this issue.  This will remove the need for most of the proposed magic in
 pecl/phar/TODO.
 * ensuring full code coverage of tests, we're currently at about 68-70%
 * finishing up Steph's work on data-only tar/zip support
(non-executable tar/zip read/write)
 * 2 open bugs at pecl.php.net
 * more hammering should be done on the web front controller to ensure
edge cases have been considered

Areas of phar that are rock-solid:
 * phar stream read/write
 * file format support for the 3 file formats read/write
 * anything else not yet mentioned.

I expect to be able to wrap up the issues listed very quickly.  Tony has
been fantastic at finding memleaks/segfaults as new features are added,
and we welcome the minutest scrutiny.

 And I'm still not convinced we should include any PECL extensions in the core,
 I believe it should go the other way round.

This is secondary, but I'm proposing using phar to test the mechanism
that will allow ext/ to migrate to pecl/ and still work as it did in ext/

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] profiling followup on addition of streams to include_path - it's *faster*

2008-03-07 Thread Gregory Beaver
Hi,

When I posted yesterday's patch to add stream support to include_path
(http://news.php.net/php.internals/36031) I mentioned that I suspected
benchmarking would reveal it to be slow.  My primary goal is to provide
no impact on current users who are using a traditional include_path,
with a secondary goal of improving performance of those who use the new
syntax.  Today I ran callgrind on the thing, with some surprising results.

With the patch, include is *faster* for our traditional users than it is
now.
With the patch, include_once with 1000 unique files is about 3% slower
- not the whole execution, just include_once
With the patch, include_once with 1 unique file included 1 times is
insignificantly slower (about 0.4%)

For these reasons, I'm really encouraged :).  The next step is to
absolutely ensure correctness and then see if the streams part of
include_path  can be optimized at all (or if it needs it).

Details
==

I just ran callgrind on this script:

?php
set_include_path('.:/usr/local/lib/php:/home/cellog/workspace/php5/ext/phar');
for ($i = 0; $i  10; $i++) {
include 'extra.php';
}

The empty file extra.php (zero byte) is in
/home/cellog/workspace/php5/ext/phar/extra.php ensuring that we
traverse include_path to find it.

To my great shock, the script runs *faster* with my patch, because it
executes significantly more instruction cycles in
php_stream_open_for_zend_ex without the patch.

Note that this does not measure the cost of *_once.  *_once is a lot
harder to measure, so I created 10,000 files (yikes) via this script:

?php
for ($i = 1; $i = 1; $i++) file_put_contents('test' . $i, '');

and then ran this test script:

?php
set_include_path('.:/usr/local/lib/php:/home/cellog/workspace/php5/poop');
for ($i = 1; $i = 1; $i++) {
include_once 'test' . $i;
}

callgrind reported that php_resolve_path was about twice as slow as the
other version, resulting in a 3% degradation of include_once performance
over the current version (which is much faster than 5.2.x, incidentally).

Finally, to test the _once aspect of include_once, I ran this script:

?php
set_include_path('.:/usr/local/lib/php:/home/cellog/workspace/php5/ext/phar');
for ($i = 0; $i  10; $i++) {
include_once 'extra.php';
}

With this script, it really highlights the most common use case of
include/require_once: attempting to include the same file multiple
times.  The difference in performance was insignificant, with callgrind
reporting a total execution portion of 75.12% for CVS, and 75.57% with
my patch.

So, it looks like the biggest performance hit would be for users
including more than 1000 different files, and would result in
approximately 3% slower performance *of include_once*.  I'm curious how
many of our readers have a PHP setup that includes close to this many
files, because it seems rather unlikely to me that anyone would include
more than a few hundred in a single process.

The surprising news is that users who are using include would see a
performance improvement from my patch, so I recommend that portion be
committed regardless of other actions.  This improvement proabbly
results from removing an include_path search in plain_wrapper.

Thanks,
Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] [PATCH] php_resolve_path correctness update (broken in CVS as well)

2008-03-07 Thread Gregory Beaver
Hi,

php_resolve_path does not exit if passed a stream wrapper, but instead
tries to find it in include_path.  This can cause really weird error
messages and breaks pecl/phar completely (and probably other stream
wrappers), so I added stream wrapper detection to the exit shunt in the
start of php_resolve_path.

The patch is otherwise the same as yesterday's.

Greg
Index: main/fopen_wrappers.c
===
RCS file: /repository/php-src/main/fopen_wrappers.c,v
retrieving revision 1.175.2.3.2.13.2.7
diff -u -r1.175.2.3.2.13.2.7 fopen_wrappers.c
--- main/fopen_wrappers.c   5 Mar 2008 13:34:12 -   
1.175.2.3.2.13.2.7
+++ main/fopen_wrappers.c   8 Mar 2008 06:11:31 -
@@ -447,6 +447,9 @@
char resolved_path[MAXPATHLEN];
char trypath[MAXPATHLEN];
char *ptr, *end;
+   php_stream_wrapper *wrapper;
+   const char *p;
+   int n = 0;
 
if (!filename) {
return NULL;
@@ -462,21 +465,52 @@
return NULL;
}
}
+   /* test for stream wrappers and return */
+   for (p = filename; p - filename  filename_length  (isalnum((int)*p) 
|| *p == '+' || *p == '-' || *p == '.'); p++) {
+   n++;
+   }
+
+   if (n  filename_length - 3  (*p == ':')  (!strncmp(//, p+1, 2) 
|| ( filename_length  4  !memcmp(data, filename, 4 {
+   /* found stream wrapper, this is an absolute path until stream 
wrappers implement realpath */
+   return estrndup(filename, filename_length);
+   }
 
-   ptr = path;
+   ptr = (char *) path;
while (ptr  *ptr) {
+   int len, is_stream_wrapper = 0, maybe_stream = 1;
+
end = strchr(ptr, DEFAULT_DIR_SEPARATOR);
+#ifndef PHP_WIN32
+   /* search for stream wrapper */
+   if (end - ptr  = 1) {
+   maybe_stream = 0;
+   goto not_stream;
+   }
+   for (p = ptr, n = 0; p  end  (isalnum((int)*p) || *p == '+' 
|| *p == '-' || *p == '.'); p++) {
+   n++;
+   }
+
+   if (n == end - ptr  *p  !strncmp(//, p+1, 2)) {
+   is_stream_wrapper = 1;
+   /* seek to real end of include_path portion */
+   end = strchr(end + 1, DEFAULT_DIR_SEPARATOR);
+   } else {
+   maybe_stream = 0;
+   }
+not_stream:
+#endif
if (end) {
if ((end-ptr) + 1 + filename_length + 1 = MAXPATHLEN) {
ptr = end + 1;
continue;
}
memcpy(trypath, ptr, end-ptr);
+   len = end-ptr;
trypath[end-ptr] = '/';
memcpy(trypath+(end-ptr)+1, filename, 
filename_length+1);
ptr = end+1;
} else {
-   int len = strlen(ptr);
+   len = strlen(ptr);
 
if (len + 1 + filename_length + 1 = MAXPATHLEN) {
break;
@@ -486,6 +520,35 @@
memcpy(trypath+len+1, filename, filename_length+1);
ptr = NULL;
}
+
+   if (!is_stream_wrapper  maybe_stream) {
+   /* search for stream wrapper */
+   for (p = trypath; isalnum((int)*p) || *p == '+' || *p 
== '-' || *p == '.'; p++) {
+   n++;
+   }
+   }
+
+   if (is_stream_wrapper || (n  len - 3  (*p == ':')  (n  1) 
 (!strncmp(//, p+1, 2) || !memcmp(data, trypath, 4 {
+   char *actual;
+
+   wrapper = php_stream_locate_url_wrapper(trypath, 
actual, STREAM_OPEN_FOR_INCLUDE TSRMLS_CC);
+   if (wrapper == php_plain_files_wrapper) {
+   strncpy(trypath, actual, MAXPATHLEN);
+   } else if (!wrapper) {
+   /* if wrapper is NULL, there was a mal-formed 
include_path stream wrapper, so skip this ptr */
+   continue;
+   } else {
+   if (wrapper-wops-url_stat) {
+   php_stream_statbuf ssb;
+
+   if (SUCCESS == 
wrapper-wops-url_stat(wrapper, trypath, 0, ssb, NULL TSRMLS_CC)) {
+   return estrdup(trypath);
+   }
+   }
+   continue;
+   }
+   }
+
if (tsrm_realpath(trypath, resolved_path TSRMLS_CC)) {
return estrdup(resolved_path);
   

[PHP-DEV] Re: 5.3 Release Planning

2008-03-06 Thread Gregory Beaver
Johannes Schlüter wrote:
 Hi all,
 
 recently there were quite a few proposals about stuff for 5.3. If we 
 implement 
 them all we won't finish in a soonish time and we get new ideas postponing 
 the 5.3  release therefore the following:
 
 - Scanner based on re2c:
   Going to re2c promises to make maintenance simpler and increase the parsers 
   performance. Currently the prototype does not provide support for Zend 
   multibyte mode. This seems doable within April. Hence I ask for finishing
   by end of April the latest. Once that is done we will go over to a freeze 
 and
   switch to bug fixing only mode. 
   If this is done sooner than we'll freeze sooner, too. If there are delays 
   we'll freeze anyways and use the scanner for a later release.
 
 - bundling pecl/intl
   According to Stas it's ready for being bundled and was voted in. The only
   question I see there is the how to bundle it. There we should definitely
   find a better thing than symlinking around on the CVS server, an option
   might be to to switch to subversion and use svn:externals or keeping stuff
   in pecl and then having some scripts (maybe part of buildconf/the release 
   scripts) fetching them into a checkout. Just ideas ... For the moment 
   symlinking might be the best.
 
 - bundling pecl/phar
   Lots of work has been done there, I'd like to have it in, general PECL
   discussion: See above.

Hi,

Just a quick note: I'd like to consider another possible approach,
having pecl/phar synced from stable pecl release.  I think this can be
done via a simple configure script that wgets the latest stable and uses
a clever little PHP_Archive-based phar to extract the source files.
There are of course other ways to do this that may be better than my
quick-and-dirty description, but it is certainly possible.  As the
primary maintainer of the PEAR installer, this would make it easier for
me to fix issues found in this process.  Because phar is new, this will
give more wiggle room for experimenting, and what we figure out could
then be used to allow the current vaporware proposal of moving all exts
to pecl.

I am also fine with symlinking until this can be perfected, as it is
just an idea to be implemented right now.

phar is in a state of slight flux: if stream wrappers get supported
inside include_path, it would change a lot of the implementation stuff
I've needed to do, and greatly simplify phar, so it will continue to
improve with this addition.

Greg

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



  1   2   3   >